006.Ansible自定義變量


ansible支持變量,用於存儲會在整個項目中重復使用到的一些值。以簡化項目的創建與維護,降低出錯的機率。

變量的定義:

  • 變量名應該由字母、數字下划數組成
  • 變量名必須以字母開頭
  • ansible內置關鍵字不能作為變量名

1. 在Inventory中定義變量

1.1. 定義主機變量

1.1.1. 內置主機變量

所謂內置變量其實就是ansible.cfg配置文件中的選項,在其前加上ansible_即成為內置變量。當然內置變擁有比ansible.cfg中選項更高的優先級,而且針對不同的主機,可以定義不同的值。

# 一般連接
ansible_ssh_host     #用於指定被管理的主機的真實IP
ansible_ssh_port     #用於指定連接到被管理主機的ssh端口號,默認是22
ansible_ssh_user     #ssh連接時默認使用的用戶名

# 特定ssh連接
ansible_connection   #SSH連接的類型:local, ssh, paramiko,在ansible 1.2 之前默認是paramiko,后來智能選擇,優先使用基於ControlPersist的ssh(如果支持的話)
ansible_ssh_pass     #ssh連接時的密碼
ansible_ssh_private_key_file  #秘鑰文件路徑,如果不想使用ssh-agent管理秘鑰文件時可以使用此選項
ansible_ssh_executable  #如果ssh指令不在默認路徑當中,可以使用該變量來定義其路徑

# 特權升級
ansible_become      #相當於ansible_sudo或者ansible_su,允許強制特權升級
ansible_become_user #通過特權升級到的用戶,相當於ansible_sudo_user或者ansible_su_user
ansible_become_pass # 提升特權時,如果需要密碼的話,可以通過該變量指定,相當於ansible_sudo_pass或者ansible_su_pass
ansible_sudo_exec   #如果sudo命令不在默認路徑,需要指定sudo命令路徑

# 遠程主機環境參數
ansible_shell_executable   # 設置目標機上使用的shell,默認為/bin/sh
ansible_python_interpreter #用來指定python解釋器的路徑,默認為/usr/bin/python 同樣可以指定ruby 、perl 的路徑
ansible_*_interpreter      #其他解釋器路徑,用法與ansible_python_interpreter類似,這里"*"可以是ruby或才perl等其他語言

下面是一個簡單的示例:

192.168.132.131 ansible_ssh_user=ansible ansible_become_user=user1  ansible_become_method=sudo ansible_become_pass="redhat" 
192.168.132.132  ansible_python_interpreter=/usr/local/python3/bin/python3
192.168.132.133  ntpserver=192.168.132.134 zabbixserer=192.168.132.134

1.2 定義主機組變量

變量也可以通過組名,應用到組內的所有成員:

[web]
node1
node2
[web:vars]
ntpserver=192.168.132.134

[root@node1 ansible]# vim vars_play1.yml

- hosts: web
  tasks:
    - package:
        name:  ntpdate
        state: present
    - cron:
        name: sync time
        minute: "*/5"
        job: "ntpdate {{ ntpserver }}"

[root@node1 ansible]# ansible-playbook   vars_play1.yml

PLAY [web] ********************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
ok: [node1]
ok: [node2]
TASK [package] ****************************************************************************************************
changed: [node2]
changed: [node1]
TASK [cron] *******************************************************************************************************
changed: [node1]
changed: [node2]
PLAY RECAP ********************************************************************************************************
node1                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node2                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

 檢查

[root@node1 ansible]# ansible web -m shell -a "crontab -l"

node2 | CHANGED | rc=0 >>
#Ansible: tectcron
* * * * * echo `date` >> /tmp/test.txt
#Ansible: sync time
*/5 * * * * ntpdate 192.168.132.134
node1 | CHANGED | rc=0 >>
#Ansible: tectcron
* * * * * echo `date` >> /tmp/test.txt
#Ansible: sync time
*/5 * * * * ntpdate 192.168.132.134

變量的優先級,主機變量擁有最高的優先級

[web]
node1 ntpserver=ntp1.aliyun.com 
node2
[web:vars]
ntpserver=192.168.132.134

2. 在Playbook中定義變量

2.1. 變量的定義方式

2.1.1. 通過vars關鍵字定義

擁有比主機和主機組更高的優先級

前面的一個示例:

- hosts: web
  vars: 
    ntpserver: ntp2.aliyun.com
  tasks:
    - package:
        name:  ntpdate
        state: present
    - cron:
        name: sync time
        minute: "*/5"
        job: "ntpdate {{ ntpserver }}"

[root@node1 ansible]# ansible-playbook vars_play1.yml

[root@node1 ansible]# ansible web -m shell -a "crontab -l"

node1 | CHANGED | rc=0 >>
#Ansible: tectcron
* * * * * echo `date` >> /tmp/test.txt
#Ansible: sync time
*/5 * * * * ntpdate ntp2.aliyun.com
node2 | CHANGED | rc=0 >>
#Ansible: tectcron
* * * * * echo `date` >> /tmp/test.txt
#Ansible: sync time
*/5 * * * * ntpdate ntp2.aliyun.com

自定義變量,debug調試

- hosts: web
  vars: 
    ntpserver: ntp2.aliyun.com
    # users: [{"name":"natasha","gender"},{"name":"tom","gender":"male" }]
    users:
      - name: natasha
        gender: famale
      - name: tom
        gender: male
  tasks:
    - debug:
        msg: "print users: {{ users }}"
    - debug:
        var: users

[root@node1 ansible]# ansible-playbook vars_play1.yml

PLAY [web] ************************************************************************************************************************************
TASK [debug] **********************************************************************************************************************************
ok: [node1] => {
    "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]"
}
ok: [node2] => {
    "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]"
}
TASK [debug] **********************************************************************************************************************************
ok: [node1] => {
    "users": [
        {
            "gender": "famale", 
            "name": "natasha"
        }, 
        {
            "gender": "male", 
            "name": "tom" } ]
}
ok: [node2] => {
    "users": [
        {
            "gender": "famale", 
            "name": "natasha"
        }, 
        {
            "gender": "male", 
            "name": "tom"
        }
    ]
}

2.1.2. 通過vars_files關鍵字引入變量文件

下面是一個簡單示例:

- hosts: web
  vars_files:
    - ntp.yml
    - users.yml
  tasks:
    - package:
        name:  ntpdate
        state: present
    - cron:
        name: sync time
        minute: "*/5"
        job: "ntpdate {{ ntpserver }}"
    - debug:
        msg: "print users: {{ users }}"
    - debug:
        var: users

[root@node1 ansible]# vim ntp.yml

ntpserver: ntp3.aliyun.com

[root@node1 ansible]# vim users.yml

users:
  - name: natasha
    gender: famale
  - name: tom
    gender: male

變量的定義格式是成鍵值對出現的,鍵值對之間可以嵌套,最終形成一個大字典,效果和前面一樣

2.2 在playbook中通過host_vars和group_vars目錄定義變量

定義inventory

demo5.example.com
[datacenter1]
demo1.example.com
demo2.example.com

[datacenter2]
demo3.example.com
demo4.example.com

[webserver]
demo1.example.com demo2.example.com demo3.example.com [mysqlserver] demo4.example.com demo5.example.com [datacenters:children] datacenter1 datacenter2

創建兩個目錄

[root@node1 ansible]# mkdir group_vars
[root@node1 ansible]# mkdir host_vars

這兩個目錄用於存放變量的配置文件

主機組使用變量

[root@node1 ansible]# vim group_vars/datacenter1
package: "tomacat1"
[root@node1 ansible]# vim group_vars/datacenter2
package: "tomacat2"
[root@node1 ansible]# vim group_vars/datacenters
package: "tomacat3"
[root@node1 ansible]# vim group_vars/mysqlserver
package: "mysql"

主機變量

[root@node1 ansible]# vim host_vars/demo1.example.com
package: "nginx1"
[root@node1 ansible]# vim host_vars/demo3.example.com
package: "nginx3"
[root@node1 ansible]# vim host_vars/demo5.example.com
package: "nginx5"

目錄結構

[root@node1 ansible]# tree 
.
├── ansible.cfg
├── group_vars
│   ├── datacenter1
│   ├── datacenter2
│   ├── datacenters
│   └── mysqlserver
├── hosts
├── host_vars
│   ├── demo1.example.com
│   ├── demo3.example.com
│   └── demo5.example.com
├── inventory
└── roles

[root@node1 ansible]# cat datacenter.yml

- hosts:  datacenter1
  tasks:
    - name: fetch vars
      debug:
         msg: "{{ package}}"

執行

TASK [fetch vars] *****************************************************************************************************************************
ok: [demo1.example.com] => {
    "msg": "nginx1"
}
ok: [demo2.example.com] => {
    "msg": "tomacat1"
}

[root@node1 ansible]# vim datacenter.yml

- hosts: all
  tasks:
    - name: fetch vars
      debug:
         msg: "{{ package}}"

root@node1 ansible]# ansible-playbook datacenter.yml 

TASK [fetch vars] *****************************************************************************************************************************
ok: [demo4.example.com] => {
    "msg": "tomcat2"
}
ok: [demo5.example.com] => {
    "msg": "nginx5"
}
ok: [demo1.example.com] => {
    "msg": "nginx1"
}
ok: [demo2.example.com] => {
    "msg": "tomacat1"
}
ok: [demo3.example.com] => {
    "msg": "nginx3"
}

如果主機組定義的變量與主機沖突,主機變量優先級最高

2.3  注冊變量

在有些時候,可能需要將某一條任務執行的結果保存下來,以便在接下的任務中調用或者做些判斷。可以通過register關鍵字來實現將某一任務結果保存為一個變量。

注冊變量的應用場景:

  • 在一台遠端的服務器獲取一個目錄下的一列表的文件,然后下載這些文件
  • 在handler執行之前,發現前面一個task發生了changed,然后執行一個指定的task
  • 獲取遠端服務器的ssh key的內容,構建出known_hosts文件

[root@node1 ansible]# vim var_test.yml

- hosts: demo5.example.com
  tasks:
    - name: list /home
      shell: ls /home
      register: list
    - debug:
        var: list

[root@node1 ansible]# ansible-playbook var_test.yml

PLAY [demo5.example.com] **********************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************
ok: [demo5.example.com]
TASK [list /home] *****************************************************************************************************************************
changed: [demo5.example.com]
TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "list": {
        "changed": true, 
        "cmd": "ls /home", 
        "delta": "0:00:00.005802", 
        "end": "2020-01-28 13:09:38.768490", 
        "failed": false, 
        "rc": 0,    #命令執行的正常的返回
        "start": "2020-01-28 13:09:38.762688", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "ansible\njoy",   #換行輸出
        "stdout_lines": [      #這個包含也是的是正常的返回
            "ansible", 
            "joy"
        ]
    }
}
PLAY RECAP ************************************************************************************************************************************
demo5.example.com          : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

當shell執行報錯,錯誤可以使用ignore_error忽略,繼續執行

[root@node1 ansible]# vim var_test.yml

- hosts: demo5.example.com
  tasks:
    - name: list /home
      shell: ls /home
      register: list
    - shell: error_test
      register: error
      ignore_errors: True
    - debug:
        var: list
    - debug:
        var: error

[root@node1 ansible]# ansible-playbook var_test.yml

PLAY [demo5.example.com] **********************************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************************************
ok: [demo5.example.com]
TASK [list /home] *****************************************************************************************************************************
changed: [demo5.example.com]
TASK [shell] **********************************************************************************************************************************
fatal: [demo5.example.com]: FAILED! => {"changed": true, "cmd": "error_test", "delta": "0:00:00.004308", "end": "2020-01-28 13:21:53.726688", "msg": "non-zero return code", "rc": 127, "start": "2020-01-28 13:21:53.722380", "stderr": "/bin/sh: error_test: command not found", "stderr_lines": ["/bin/sh: error_test: command not found"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "list": {
        "changed": true, 
        "cmd": "ls /home", 
        "delta": "0:00:00.005806", 
        "end": "2020-01-28 13:21:53.151761", 
        "failed": false, 
        "rc": 0,     #正常返回
        "start": "2020-01-28 13:21:53.145955", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "ansible\njoy", 
        "stdout_lines": [
            "ansible", 
            "joy"
        ]
    }
}
TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "error": {
        "changed": true, 
        "cmd": "error_test", 
        "delta": "0:00:00.004308", 
        "end": "2020-01-28 13:21:53.726688", 
        "failed": true, 
        "msg": "non-zero return code", 
        "rc": 127,    #命令不存在返回
        "start": "2020-01-28 13:21:53.722380", 
        "stderr": "/bin/sh: error_test: command not found",     #找到不到命令
        "stderr_lines": [
            "/bin/sh: error_test: command not found"
        ], 
        "stdout": "", 
        "stdout_lines": []
    }
}
PLAY RECAP ************************************************************************************************************************************
demo5.example.com          : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

2.4 通過命令行設置變量

- hosts: '{{ hosts }}'
  remote_user: '{{ user }}'
  tasks:
    - debug: 
        var: hosts
    - debug:
        var: user

[root@node1 ansible]# ansible-playbook var_test.yml --extra-vars "hosts=demo5.example.com user=ansible"  

或者

[root@node1 ansible]# ansible-playbook var_test.yml --extra-vars '{"hosts":"demo5.example.com","user":"ansible"}'

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "hosts": "demo5.example.com"
}

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "user": "ansible"
}

2.5 變量的使用和調試

定義一個變量文件

[root@node1 ansible]# vim users.yml

users:
  - name: natash
    gender: female
    hobby:
      - swimming
      - running
  - name: tom
    gender: male
    hobby:
      - football
      - basketball
      - sleepping

[root@node1 ansible]# vim use_users.yml

- hosts: demo5.example.com
  vars_files:                  #調用變量文件
    - users.yml
  tasks:
    - debug:
        var: users             #獲取users變量的信息結構等

[root@node1 ansible]# ansible-playbook use_users.yml

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {    #user變量的結構
    "users": [    #列表有序   
        {
            "gender": "female", 
            "hobby": [
                "swimming", 
                "running"
            ], 
            "name": "natash"
        }, 
        {
            "gender": "male", 
            "hobby": [
                "football", 
                "basketball", 
                "sleepping"
            ], 
            "name": "tom"
        }
    ]
}

獲取user當中,第一個用戶的第一個愛好

- hosts: demo5.example.com
  vars_files:
    - users.yml
  tasks:
    - debug:
        var: users[0].hobby[0]            #第一個用戶的第一個愛好
    - debug:
        msg: "{{ users[1].hobby[2] }}"    #第二個用戶的第三個愛好

執行輸出

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "users[0].hobby[0]": "swimming"
}

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "msg": "sleepping"
}

重新定義變量

[root@node1 ansible]# vim users.yml 

users:
  natash:
    - name: natash
      gender: female
      hobby:
        - swimming
        - running
  tom:
    - name: tom
      gender: male
      hobby:
        - football
        - basketball
        - sleepping

[root@node1 ansible]# vim use_users.yml 

- hosts: demo5.example.com
  vars_files:
    - users.yml
  tasks:
    - debug:
        var: users.natash[0].hobby[0]
    - debug:
        msg: "{{ users.tom[0].hobby }}"   #獲取所有愛好

[root@node1 ansible]# ansible-playbook use_users.yml 

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => {
    "users.natash[0].hobby[0]": "swimming"
}

TASK [debug] **********************************************************************************************************************************
ok: [demo5.example.com] => { 
    "msg": [
        "football", 
        "basketball", 
        "sleepping"
    ]
}

另外的引用變量方式

    - debug:
        var: users.natash.0.hobby.0
    - debug:
        msg: "{{ users.tom.0.hobby }}"
    - debug:
        msg: "{{ users['tom'][0]['hobby'] }}"

2.6 關於debug介紹

關於輸出的debug部分重點說明如下:

  • login: 變量名,其值為一個字典
  • changed:ansible基於此來判斷是否發生了狀態改變
  • cmd:被調用的命令
  • failed:是否運行失敗
  • rc:返回值,0代表正常,非0代表異常
  • stderr:如果出現異常,會在這里顯示錯誤輸出
  • stderr_lines:按行分割的錯誤輸出
  • stdout:如果指令正常運行,則在這里輸出返回結果
  • stdout:按行分割的返回結果

需要說明的是,通過register注冊的變量的結果並不是一成不變的,在不確定返回值的情況下,盡量調試看看輸出結果。

關於debug的更多用法說明:

調試模塊,用於在調試中輸出信息
常用參數:

  • msg:調試輸出的消息
  • var:將某個變量傳遞給debug模塊,debug會直接將其打印輸出
  • verbosity:debug的級別

 博主聲明:本文的內容來源主要來自譽天教育晏威老師,由本人實驗完成操作驗證,需要的博友請聯系譽天教育(http://www.yutianedu.com/),獲得官方同意或者晏老師(https://www.cnblogs.com/breezey/)本人同意即可轉載,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM