Linux架構27 Ansible變數, 定義變數的方式, 變數註冊, facts快取

战斗小人發表於2024-03-29

Ansible變數

一、變數概述

變數提供了便捷的方式來管理Ansible playbook的每一個專案中的動態值,比如nginx-1.6.3這個軟體包的版本,在其他地方或許會反覆使用,
那麼如果講此值設定為變數,然後再在其他的playbook中呼叫,會方便許多。如此一來還方便維護,減少維護的成本。

二、定義變數的方式

1.透過命令列進行變數定義
2.在play檔案中進行變數定義
3.透過Inventory主機資訊檔案中進行變數定義
4.透過vars_files定義變數
5.透過host_vars和group_vars定義變數

如果在定義變數時,變數衝突了
在上述的三個地方分別設定了:
    1.命令列中:age=11
    2.play檔案中:age=12
    3.Inventory中:age=13
    那麼,最終的age結果一定是11
    變數的讀取優先順序為:命令列 > playbook檔案 > Inventory檔案
    
#注意:變數命名,應該由字母、數字、下劃線組成,必須以字母開頭

1.在playbook檔案中進行變數定義

1)方式一:在模組下定義變數

- name: Install LNMP
  yum:
      name: "{{ packages }}"
  vars:
      packages:
        - nginx
        - php
        - mariadb-server

2)方式二:在hosts下面直接定義變數

[root@m01 base]# vim install.yml
- hosts: web_group
  vars:
    package:
      - httpd
      - mariadb-server
      - MySQL-python
      - php
      - nginx
  tasks:
    - name: Install Server
      yum:
        name: "{{ package }}"

3)方式三:在hosts下面直接定義多個變數

[root@m01 base]# vim install.yml
- hosts: web_group
  vars:
    web:
      - httpd
      - nginx
    db:
      - mariadb-server
      - MySQL-python
      
  tasks:
    - name: Install Server
      yum:
        name: "{{ web }}"
        
    - name: Install DB Server
      yum:
        name: "{{ db }}"

2.透過vars_files定義變數

剛才我們學到在playbook中使用vars定義變數,有一個缺陷,就是其他的playbook無法使用該變數。

所以我們可以採取第二種定義變數的方式,在vars_file中定義變數。

#1.配置變數檔案
[root@m01 base]# vim vars.yml
web_server: nginx
db_server: mariadb-server

#2.呼叫變數檔案再使用變數
[root@m01 base]# vim host.yml
- hosts: db_group
  vars_files: /project/base/vars.yml
  tasks:
    - name: Install Mariadb Server
      yum:
        name: "{{ db_server }}"

#3.定義多個變數檔案
[root@m01 base]# vim host.yml
- hosts: db_group
  vars_files: 
      - /project/base/vars.yml
      - /project/base/vars2.yml
  tasks:
    - name: Install Mariadb Server
      yum:
        name: "{{ nginx }}"

3.直接使用內建變數

[root@m01 ~]# ansible "web01" -m setup    #setup模組,獲取主機資訊(看內建變數)
web01 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.0.7", 
            "172.16.1.7"
        ], 
    ...

# ansible_all_ipv4_addresses就是內建變數,檢視內建變數
[root@m01 ~]# ansible "web01" -m setup -a 'filter=ansible_all_ipv4_addresses'
[root@m01 ~]# ansible "web01" -m setup -a 'filter=ansible_default_ipv4'

#直接使用內建變數
[root@m01 ~]# vim mkdir.yml
- hosts: web03
  tasks:
    - name: Create DIR
      file:
        path: /tmp/{{ ansible_default_ipv4['address'] }}#路徑下變數可以不加引號,裡面也可以.address
        state: directory

[root@m01 ~]# ansible-playbook mkdir.yml
[root@web03 tmp]# ls
10.0.0.9

#可以把內建引數寫在vars_file中,也可以定義變數再使用
[root@m01 ~]# vim mkdir.yml
- hosts: web03
  vars:
    - remote_ip: "{{ ansible_default_ipv4['address'] }}"
  tasks:
    - name: Create IP DIR
      file:
        path: /tmp/{{ remote_ip }}
        state: directory
        
#例項
[root@m01 ~]# vim mkdir.yml
- hosts: web_group
  tasks:
    - name: Create Backup DIR
      file:
        path: /backup/{{ ansible_fqdn }}_{{ ansible_default_ipv4['address'] }}_{{ ansible_date_time.date }}    #ansible_fqdn:主機名
        state: directory

[root@m01 ~]# ansible-playbook mkdir.yml
[root@web01 backup]# ls
web01_10.0.0.7_2024-03-27
[root@web02 backup]# ls
web02_10.0.0.8_2024-03-27

4.在Inventory主機清單中進行變數定義

#1.配置主機清單
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
web01 ansible_ssh_pass='admin123'
web02 ansible_ssh_pass='admin123'

[db_group]
db01 ansible_ssh_pass='admin123'
db02 ansible_ssh_pass='admin123'
db03 ansible_ssh_pass='admin123'

[web_group:vars]    #對web_group組定義變數
web_server=nginx
------------------------------------------
#2.呼叫變數
[root@m01 base]# vim install.yml
- hosts: web_group
  tasks:
    - name: Create WEB Dir
      file:
        path: /tmp/{{ web_server }}
        state: directory
#檢查結果
[root@m01 base]# ansible-playbook install.yml
[root@web01 tmp]# ls
nginx
------------------------------------------

#3.對整合組定義變數
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
web01 ansible_ssh_pass='admin123'
web02 ansible_ssh_pass='admin123'

[db_group]
db01 ansible_ssh_pass='admin123'
db02 ansible_ssh_pass='admin123'
db03 ansible_ssh_pass='admin123'

[web_group:vars]
web_server=nginx    #優先順序高於整合組的優先順序

[nfs_client:children]    #設定整合組
db_group
web_group

[nfs_client:vars]    #對整合組定義變數
web_server=http
------------------------------------------
#4.呼叫變數
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
------------------------------------------
#檢視建立目錄
[root@m01 base]# ansible 'all' -m shell -a 'ls /tmp'

#注意:
    主機組定義的變數優先順序比整合組呼叫的變數優先順序高
    先讀取整合組的變數,後讀取組的變數,則組的變數將覆蓋整合組的變數

5.透過host_vars和group_vars定義變數

之前的幾種變數定義都不是很好用,比較好用的是在Ansible專案目錄下建立兩個變數目錄:
host_vars
group_vars
切記,目錄名字一定要一致,不能做任何修改(ansible會到yml同級目錄下去找這個名字,不需要呼叫)

1)主機組定義變數

#建立組變數的目錄,不能改名字
[root@m01 base]# mkdir group_vars

#目錄下的名字要與主機清單裡面組名相同
[root@m01 base]# vim group_vars/web_group
web_server: http

#呼叫變數
[root@m01 base]# vi mkdir.yml
- hosts: web_group    # 會去yml同級目錄下group_vars裡找web_group
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory

2)主機定義變數

#建立主機變數的目錄,不能改名字
[root@m01 base]# mkdir host_vars

#目錄下的名字要與主機清單裡面主機名相同
[root@m01 base]# vim host_vars/db01
web_server: host_vars

#呼叫變數
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
#注意:
    主機組定義的變數優先順序比整合組呼叫的變數優先順序高,主機定義的變數優先順序比主機組定義的變數優先順序高

6.透過命令列進行變數定義(使用--extra-vars或者-e設定變數)

[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
        
#命令列指定變數的值
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=commond"

#遠端檢視檔案
[root@m01 base]# ansible 'all' -m shell -a 'ls /tmp'

#指定多個變數
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory
        
    - name: Create db DIR
      file:
        path: /tmp/{{ db_server }}
        state: directory
        
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=commond" -e "db_server=mysql"

7.變數引用優先順序測試

#配置playbook變數
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  vars:
    web_server: playbook_vars
  vars_files:
    - ./vars_file.yml
  tasks:
    - name: Create Backup DIR
      file:
        path: /opt/{{ web_server }}
        state: directory
        
#配置var_file變數
[root@m01 base]# vim var_file.yml
web_server: vars_files

#主機清單定義變數
[root@m01 base]# vim /etc/ansible/hosts
[web_group:vars]
web_server=inventory_vars

#host_vars定義變數
[root@m01 base]# vim host_vars/web01
web_server: host_vars

#group_vars定義變數
[root@m01 base]# vim group_var/web_group
web_server: group_vars

#命令列變數
[root@m01 base]# ansible-playbook mkdir.yml -e "web_server=command"

#測試後優先順序結果:
命令列 > var_files > playbook_vars > host_vars > group_vars配置組變數 > group_vars配置整合組變數 > 主機清單定義組變數 > 主機清單定義整合組變數

8.層級定義變數 (很少這麼用)

[root@m01 ~]# vim vars_file.yml
lamp:
  framework:
    web_package: httpd
    db_package: mariadb-server
    php_package: php
    
lnmp:
  framework:
    web_package: nginx
    db_package: mysql
    php_package: php
    
lnmt:
  framework:
    web_package: nginx
    db_package: mysql
    php_package: tomcat
    
#編輯playbook檔案
[root@m01 ~]# vim test.yml
- hosts: web_group
  vars_files: ./vars_file.yml
  tasks:
    - name: Install LAMP httpd
      yum:
        name: "{{ lamp.framework.web_package }}"    #不能寫lamp.framework,不認

    - name: Install LAMP mariadb-server
      yum:
        name: "{{ lamp.framework.db_package }}"
        
    - name: Install LAMP php
      yum:
        name: "{{ lamp.framework.php_package }}"
        
#官方推薦寫法
[root@m01 ~]# vim test.yml
- hosts: web_group
  vars_files: ./vars_file.yml
  tasks:
    - name: Install LAMP httpd
      yum:
        name: "{{ lamp['framework']['web_package'] }}"

    - name: Install LAMP mariadb-server
      yum:
        name: "{{ lamp['framework']['db_package'] }}"
        
    - name: Install LAMP php
      yum:
        name: "{{ lamp['framework']['php_package'] }}"

三、變數註冊

當ansible的模組在執行之後,其實都會返回一些result結果,就像是執行指令碼,我們有的時候需要指令碼給我們一些return返回值,我們才知道,
上一步是否可以執行成功,但是...預設情況下,ansible的result並不會顯示出來,所以,我們可以把這些返回值'儲存'到變數中,
這樣我們就能透過'呼叫'對應的變數名,從而獲取到這些result,這種將模組的返回值,寫入到變數中的方法被稱為變數註冊

1.變數註冊配置

#建立目錄獲取過程
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: Create Dir
      file:
        path: /tmp/{{ ansible_fqdn }}
        state: directory
      register: get_mkdir_status    #register獲取上面建立的過程放到自己定義的變數中

    - name: Get register
      debug:    #用於輸出內容
        msg: "{{ get_mkdir_status }}"
        
[root@m01 ~]# ansible-playbook test.yml

#檢視目錄,執行得不到想要的結果
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"

#使用變數註冊獲取想要的結果
[root@m01 ~]# vim test.yml
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"
      register: list_dir

    - name: Get list_dir
      debug:
        msg: "{{ list_dir }}"
        
#只輸出我們想要的內容
- hosts: web01
  tasks:
    - name: List Dir /tmp
      shell: "ls -l /tmp"
      register: list_dir

    - name: Get list_dir
      debug:
        msg: "{{ list_dir.stdout_lines }}"
        #msg: "{{ list_dir['stdout_lines'] }}"    #官方寫法也可以

2.變數註冊一般使用場景(判斷)

[root@m01 ~]# vim status.yml
- hosts: web01
  tasks:
    - name: Install Httpd Server
      yum:
        name: httpd

    - name: Check httpd Status
      shell: systemctl is-active httpd
      ignore_errors: yes    #忽略報錯(如果不寫,返回錯誤就結束了,不會往下走)
      register: check_httpd

    - name: Http Restart    #返回啟動,就重啟
      systemd:
        name: httpd
        state: restarted
      when: check_httpd.rc == 0

    - name: Http Start        #返回異常,就啟動
      systemc:
        name: httpd
        state: started
      when: check_httpd.rc != 0

四、facts快取

Ansible facts是在被管理主機上透過Ansible自動採集發現的變數。facts包含每臺特定的主機資訊。比如:
被控端的主機名、IP地址、系統版本、CPU數量、記憶體狀態、磁碟狀態等等。 setup模組獲取的資訊都是因為 facts快取

1.facts使用場景

1.透過facts快取檢查CPU,來生成對應的nginx配置檔案
2.透過facts快取檢查主機名,生成不同的zabbix配置檔案
3.透過facts快取檢索物理機的記憶體大小來生成不通的mysql配置檔案

綜上所述的Ansible facts類似於saltstack中的grains對於做自動化的小夥伴是非常有用的。

2.關閉facts

#如果使用ansible內建變數的話,不能關閉facts快取
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  gather_facts: false    #跳過gather_facts步驟,速度變快,但是無法獲取內建變數
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ ansible_fqdn }}
        state: directory
[root@m01 base]# ansible-playbook mkdir.yml #報錯,無法獲取ansible_fqdn變數

#如果不使用ansible內建變數的話,關閉facts會提高ansible管理其他機器的速度
[root@m01 base]# vim mkdir.yml
- hosts: nfs_client
  gather_facts: false    #跳過gather_facts步驟,速度變快,但是無法獲取內建變數
  tasks:
    - name: Create Backup DIR
      file:
        path: /tmp/{{ web_server }}
        state: directory

3.一般配置

[root@m01 base]# vim redis.yml
bind {{ ansible_default_ipv4['address'] }}

[root@m01 base]# vim conf.yml
- hosts: all
  tasks:
    - name: Config Redis Conf
      template:    #識別內建變數要用template模組,copy模組無法識別
        src: ./redis.conf
        dest: /tmp/

#遠端檢視
[root@web01 tmp]# cat redis.conf
bind 10.0.0.7

相關文章