我們?cè)赑layBook一節(jié)中伍纫,將PlayBook類比成了Linux中的shell宗雇。那么它作為一門Ansible特殊的語(yǔ)言,肯定要涉及到變量定義莹规、控制結(jié)構(gòu)的使用等特性赔蒲。在這一節(jié)中主要討論變量的定義和使用。
變量命名規(guī)則
變量的名字由字母良漱、下劃線和數(shù)字組成舞虱,以字母開(kāi)頭。
如下變量命名為正確:
good_a OK
ok_b OK
如下變量命名為錯(cuò)誤:
_aaa FAIL
2_bb FAIL
保留關(guān)鍵字不能作為變量名稱
add, append, as_integer_ratio, bit_length, capitalize, center, clear, conjugate, copy, count,
decode, denominator, difference, difference_update, discard, encode, endswith, expandtabs,
extend, find, format, fromhex, fromkeys, get, has_key, hex, imag, index, insert, intersection,
intersection_update, isalnum, isalpha, isdecimal, isdigit, isdisjoint, is_integer, islower,
isnumeric, isspace, issubset, issuperset, istitle, isupper, items, iteritems, iterkeys,
itervalues, join, keys, ljust, lower, lstrip, numerator, partition, pop, popitem, real, remove,
replace, reverse, rfind, rindex, rjust, rpartition, rsplit, rstrip, setdefault, sort, split,
splitlines, startswith, strip, swapcase, symmetric_difference, symmetric_difference_update,
title, translate, union, update, upper, values, viewitems, viewkeys, viewvalues, zfill
變量類型
根據(jù)變量的作用范圍大體的將變量分為: 全局變量母市、劇本變量矾兜、資產(chǎn)變量。但只是一個(gè)比較粗糙的劃分患久,不能囊括Ansible 中的所有變量椅寺。下面將分別從這三種變量入手,去介紹變量的使用
全局變量
全局變量蒋失,是我們使用ansible 或使用ansible-playbook 時(shí)返帕,手動(dòng)通過(guò) -e 參數(shù)傳遞給Ansible 的變量。
通過(guò)ansible 或 ansible-playbook 的 help 幫助, 可以獲取具體格式使用方式:
# ansible -h |grep var
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON
# ansible-playbook -h |grep var
-e EXTRA_VARS, --extra-vars=EXTRA_VARS
set additional variables as key=value or YAML/JSON
示例:
傳遞普通的key=value 的形式
# ansible all -i localhost, -m debug -a "msg='my key is {{ key }}'" -e "key=value"
傳遞一個(gè)YAML/JSON 的形式(注意不管是YAML還是JSON篙挽,它們的最終格式一定要是一個(gè)字典)
# cat a.json
{"name":"qfedu","type":"school"}
# ansible all -i localhost, -m debug -a "msg='name is {{ name }}, type is {{ type }}'" -e @a.json
# cat a.yml
---
name: qfedu
type: school
...
# ansible all -i localhost, -m debug -a "msg='name is {{ name }}, type is {{ type }}'" -e @a.yml
劇本變量
此種變量和PlayBook 有關(guān)荆萤,定義在PlayBook中的。它的定義方式有多種铣卡,我們這里介紹兩種最常用的定義方式链韭。
通過(guò)PLAY 屬性 vars 定義
---
- name: test play vars
hosts: all
vars:
user: lilei
home: /home/lilei
# cat vars/users.yml
---
user: lilei
home: /home/lilei
如何在PlayBook中使用這些變量
在PlayBook中使用變量時(shí)邑闲,使用 {{ 變量名 }} 來(lái)使用變量
---
- name: test play vars
hosts: all
vars:
user: lilei
home: /home/lilei
tasks:
- name: create the user {{ user }}
user:
name: "{{ user }}"
home: "{{ home }}"
在PlayBook中使用變量的注意點(diǎn)
---
# 這里我們將上面的Playbook中引用變量的部分進(jìn)行修改,去掉了雙引號(hào)梧油。
- name: test play vars
hosts: all
vars:
user: lilei
home: /home/lilei
tasks:
- name: create the user {{ user }}
user:
# 注意這里將 "{{ user }}" 改成了 {{ user }} //沒(méi)了引號(hào)
name: {{ user }}
home: "{{ home }}”
執(zhí)行以上的PlayBook 時(shí)苫耸,會(huì)出現(xiàn)以下錯(cuò)誤
The offending line appears to be:
user:
name: {{ user }}
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
這樣錯(cuò)誤的主要原因是PlayBook 是YAML 的文件格式,YAML格式相當(dāng)嚴(yán)謹(jǐn)儡陨, 當(dāng)Ansible 分析YAML 文件時(shí)褪子,有可能會(huì)誤認(rèn)為類似name: {{ user }} 是一個(gè)字典的開(kāi)始。因此加針對(duì)變量的使用骗村,加上了雙引號(hào)嫌褪,避免Ansible錯(cuò)誤解析。
資產(chǎn)變量
資產(chǎn)共分為靜態(tài)資產(chǎn)和動(dòng)態(tài)資產(chǎn)胚股。這一節(jié)中學(xué)習(xí)的資產(chǎn)變量笼痛,就是和資產(chǎn)緊密相關(guān)的一種變量。資產(chǎn)變量分為主機(jī)變量和組變量琅拌,分別針對(duì)資產(chǎn)中的單個(gè)主機(jī)和組缨伊。
主機(jī)變量
以下資產(chǎn)中,定義了一個(gè)主機(jī)變量 lilei 进宝,此變量只針對(duì) 10.3.134.4 這臺(tái)服務(wù)器有效刻坊。
# cat inventoryandhostvars
[web_servers]
10.3.134.4 user=lilei
10.3.134.5
驗(yàn)證
// 獲取定義的變量值
# ansible 10.3.134.4 -i inventoryandhostvars -m debug -a "var=user"
10.3.134.4 | SUCCESS => {
"user": "lilei"
}
// 未獲取到定義的變量值,因?yàn)?lilei 這個(gè)變量針對(duì) 10.3.134.5 主機(jī)無(wú)效党晋。
# ansible 10.3.134.5 -i inventoryandhostvars -m debug -a "var=user"
10.3.134.5 | SUCCESS => {
"user": "VARIABLE IS NOT DEFINED!"
}
組變量
以下資產(chǎn)中谭胚,定義了一個(gè)組變量home ,此變量將針對(duì)web-servers 這個(gè)主機(jī)組中的所有服務(wù)器有效
# cat inventoryandgroupvars
[web-servers]
10.3.134.4 user=lilei
10.3.134.5
[web-servers:vars]
home="/home/lilei"
驗(yàn)證
// user 在資產(chǎn)中定義的是主機(jī)變量未玻, 所以在主機(jī) 10.3.134.5 中未獲取到變量user 值
# ansible web-servers -i inventoryandgroupvars -m debug -a "var=user"
10.3.134.4 | SUCCESS => {
"user": "lilei"
}
10.3.134.5 | SUCCESS => {
"user": "VARIABLE IS NOT DEFINED!"
}
// home 是 web-servers 的組變量灾而,會(huì)針對(duì)這個(gè)組內(nèi)的所有服務(wù)器生效。
# ansible web-servers -i inventoryandgroupvars -m debug -a "var=home"
10.3.134.4 | SUCCESS => {
"home": "/home/lilei"
}
10.3.134.5 | SUCCESS => {
"home": "/home/lilei"
}
主機(jī)變量 VS 組變量
當(dāng)主機(jī)變量和組變量在同一個(gè)資產(chǎn)中發(fā)生重名的情況扳剿,會(huì)有什么效果呢?
# cat inventory_v2
[web-servers]
10.3.134.4 user=lilei
10.3.134.5
[web-servers:vars]
user=cat
驗(yàn)證:
// 在資產(chǎn)中定義了主機(jī)變量和組變量 user, 此時(shí)發(fā)現(xiàn) 192.168.122.129 這臺(tái)機(jī)器的主機(jī)變量 user 的優(yōu)先級(jí)
// 優(yōu)先于 組變量user 使用旁趟。
# ansible web-servers -i inventory_v2 -m debug -a "var=user"
10.3.134.4 | SUCCESS => {
"user": "lilei"
}
10.3.134.5 | SUCCESS => {
"user": "cat"
}
變量繼承
在介紹資產(chǎn)時(shí)說(shuō)過(guò)資產(chǎn)的繼承,那么變量是否也存在繼承關(guān)系呢?
# cat inventory_v3
[web-servers]
10.3.134.4
[db-servers]
10.3.134.5
[all-servers]
[all-servers:children]
db-servers
web-servers
[all-servers:vars]
user=lilei
驗(yàn)證:
// 在資產(chǎn)繼承的同時(shí)舞终,對(duì)應(yīng)的變量也發(fā)生了繼承
# ansible all-servers -i inventory_v3 -m debug -a "var=user"
10.3.134.5 | SUCCESS => {
"user": "lilei"
}
10.3.134.4 | SUCCESS => {
"user": "lilei"
}
# ansible db-servers -i inventory_v3 -m debug -a "var=user"
10.3.134.5 | SUCCESS => {
"user": "lilei"
}
# ansible web-servers -i inventory_v3 -m debug -a "var=user"
10.3.134.4 | SUCCESS => {
"user": "lilei"
}
Facts變量
Facts變量不包含在前文中介紹的全局變量轻庆、劇本變量及資產(chǎn)變量之內(nèi)。Facts變量不需要我們?nèi)藶槿ヂ暶髯兞棵百x值敛劝。它的聲明和賦值完全有Ansible 中的Facts模塊幫我們完成余爆。類似于資產(chǎn)變量中的主機(jī)變量,它收集了有關(guān)被管理服務(wù)器的操作系統(tǒng)的版本夸盟、服務(wù)器的IP地址蛾方、主機(jī)名,磁盤的使用情況、CPU個(gè)數(shù)桩砰、內(nèi)存大小等等有關(guān)被管理服務(wù)器的私有信息拓春。假如我們足夠細(xì)心的話,在每次PlayBook運(yùn)行的時(shí)候都會(huì)發(fā)現(xiàn)在PlayBook執(zhí)行前都會(huì)有一個(gè)Gathering Facts的過(guò)程亚隅。這個(gè)過(guò)程就是收集被管理服務(wù)器的Facts信息過(guò)程硼莽。
手動(dòng)收集Facts 變量
# ansible all -i localhost, -c local -m setup
localhost | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.3.134.4"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fede:b5b"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/02/2015",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"KEYBOARDTYPE": "pc",
"KEYTABLE": "us",
"LANG": "en_US.UTF-8",
"SYSFONT": "latarcyrheb-sun16",
"nomodeset": true,
"quiet": true,
"rd_LVM_LV": "vg_mouse00/lv_root",
"rd_NO_DM": true,
"rd_NO_LUKS": true,
"rd_NO_MD": true,
"rhgb": true,
"ro": true,
"root": "/dev/mapper/vg_mouse00-lv_root"
},
...
...
...
過(guò)濾Facts
通過(guò)剛剛的手動(dòng)收集Facts,我們發(fā)現(xiàn)facts 信息量很大煮纵。 能不能有針對(duì)性的顯示我們想要的信息呢?
可以通過(guò)使用Facts 模塊中的filter參數(shù)去過(guò)濾我們想要的信息懂鸵。
// 比如我想要服務(wù)器的內(nèi)存情況信息
# ansible all -i localhost, -m setup -a "filter=*memory*" -c local
localhost | SUCCESS => {
"ansible_facts": {
"ansible_memory_mb": {
"nocache": {
"free": 508,
"used": 473
},
"real": {
"free": 59,
"total": 981,
"used": 922
},
"swap": {
"cached": 0,
"free": 1981,
"total": 1983,
"used": 2
}
}
},
"changed": false
}
// 比如想要服務(wù)器的磁盤掛載情況
# ansible all -i localhost, -m setup -a "filter=*mount*" -c local
localhost | SUCCESS => {
"ansible_facts": {
"ansible_mounts": [
{
"device": "/dev/mapper/vg_mouse00-lv_root",
"fstype": "ext4",
"mount": "/",
"options": "rw",
"size_available": 5795786752,
"size_total": 18435350528,
"uuid": "N/A"
},
{
"device": "/dev/sda1",
"fstype": "ext4",
"mount": "/boot",
"options": "rw",
"size_available": 442216448,
"size_total": 499355648,
"uuid": "N/A"
}
]
},
"changed": false
}
如何在PlayBook中去使用Facts 變量
默認(rèn)情況下,在執(zhí)行PlayBook的時(shí)候行疏,它會(huì)去自動(dòng)的獲取每臺(tái)被管理服務(wù)器的facts信息匆光。
---
- name: a play example
hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=present
- name: copy nginx.conf to remote server
copy: src=nginx.conf dest=/etc/nginx/nginx.conf
- name: start nginx server
service:
name: nginx
enabled: true
state: started
執(zhí)行:
# ansible-playbook myplaybook.yml
PLAY [a play example]
********************************************************************************************************************************************************
# 執(zhí)行PLAYBOOK時(shí),自動(dòng)收集facts 信息
TASK [Gathering Facts]
********************************************************************************************************************************************************
ok: [10.3.134.5]
ok: [10.3.134.5]
TASK [install nginx package]
********************************************************************************************************************************************************
ok: [10.3.134.4]
ok: [10.3.134.5]
......
......
可以像使用其他變量一樣酿联,去使用facts 變量
---
- name: print facts variable
hosts: all
tasks:
- name: print facts variable
debug:
msg: "The default IPV4 address is {{ ansible_default_ipv4.address }}" //字典取值
如何在PlayBook中去關(guān)閉Facts 變量的獲取
若在整個(gè)PlayBook 的執(zhí)行過(guò)程中终息,完全未使用過(guò)Facts 變量,此時(shí)我們可以將其關(guān)閉贞让,以加快PlayBook的執(zhí)行速度周崭。
---
- name: a play example
hosts: all
# 關(guān)閉 facts 變量收集功能
gather_facts: no
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=present
- name: copy nginx.conf to remote server
copy: src=nginx.conf dest=/etc/nginx/nginx.conf
- name: start nginx server
service:
name: nginx
enabled: true
state: started
*執(zhí)行
# ansible-playbook myplaybook2.yml
PLAY [a play example]
*********************************************************************************************************************************************
TASK [install nginx package
*********************************************************************************************************************************************
ok: [10.3.134.4]
ok: [10.3.134.5]
TASK [copy nginx.conf to remote server]
*********************************************************************************************************************************************
ok: [10.3.134.5]
ok: [10.3.134.4]
TASK [start nginx server]
*********************************************************************************************************************************************
ok: [10.3.134.5]
注冊(cè)變量:
往往用于保存一個(gè)task任務(wù)的執(zhí)行結(jié)果, 以便于debug時(shí)使用≌鹜埃或者將此次task任務(wù)的結(jié)果作為條件休傍,去判斷是否去執(zhí)行其他task任務(wù)。注冊(cè)變量在PlayBook中通過(guò)register關(guān)鍵字去實(shí)現(xiàn)蹲姐。
---
- name: web
hosts: web_server
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
register: nginx //定義變量名
- name: print
debug: var=nginx.changed //變量是一個(gè)字典,讀取對(duì)應(yīng)值
...
---
- name: install a package and print the result
hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx state=present
register: install_result
- name: print result
debug: var=install_result
執(zhí)行:
# ansible-playbook myplaybook3.yml
PLAY [a play example]
***************************************************************************************************************************************************************
TASK [Gathering Facts]
**************************************************************************************************************************************************************
ok: [10.3.134.5]
ok: [10.3.134.4]
TASK [install nginx package]
********************************************************************************************************************************************************
ok: [10.3.134.4]
ok: [10.3.134.5]
// 打印軟件包安裝結(jié)果
TASK [print result]
*****************************************************************************************************************************************************************
ok: [10.3.134.4] => {
"install_result": {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"nginx-1.12.1-1.el6.ngx.x86_64 providing nginx is already installed"
]
}
}
ok: [10.3.134.5] => {
"install_result": {
"changed": false,
"msg": "",
"rc": 0,
"results": [
"nginx-1.12.2-1.el6.ngx.x86_64 providing nginx is already installed"
]
}
}
PLAY RECAP
**************************************************************************************************************************************************************************
10.3.134.4 : ok=3 changed=0 unreachable=0 failed=0
10.3.134.5 : ok=3 changed=0 unreachable=0 failed=0
變量?jī)?yōu)先級(jí)
目前介紹了全局變量人柿、劇本變量柴墩、資產(chǎn)變量、Facts變量及注冊(cè)變量凫岖。其中Facts變量不需要人為去聲明江咳、賦值;注冊(cè)變量只需通過(guò)關(guān)鍵字register去聲明哥放,而不需要賦值歼指。而全局變量、劇本變量及資產(chǎn)變量則完全需要人為的去聲明甥雕、賦值踩身。變量的優(yōu)先權(quán)討論,也將著重從這三類變量去分析社露。
假如在使用過(guò)程中挟阻,我們同時(shí)在全局變量、劇本變量及資產(chǎn)變量聲明了同一個(gè)變量名,那么哪一個(gè)優(yōu)先級(jí)最高呢?
下面我們將以實(shí)驗(yàn)的形式去驗(yàn)證變量的優(yōu)先級(jí)
環(huán)境準(zhǔn)備
1附鸽、定義一份資產(chǎn)脱拼、且定義了資產(chǎn)變量user
[web_servers]
10.3.134.4
10.3.134.5
[web_servers:vars]
user=tomcat
2、編寫一份PlayBook坷备、同樣定義劇本變量user
---
- name: test variable priority
hosts: all
remote_user: root
vars:
user: mysql
tasks:
- name: print the user value
debug: msg='the user value is {{ user }}'
驗(yàn)證測(cè)試
同時(shí)使用全局變量熄浓、劇本變量、資產(chǎn)變量
當(dāng)變量user同時(shí)定義在全局變量省撑、劇本變量及資產(chǎn)變量中時(shí)赌蔑,全局變量的優(yōu)先級(jí)最高。
# ansible-playbook priority.yml -e "user=www"
PLAY [a play example]
***************************************************************************************************************************************************************
TASK [Gathering Facts]
**************************************************************************************************************************************************************
ok: [10.3.134.5]
ok: [10.3.134.4]
// 打印的 user 值 為www , 全局變量生效
TASK [print the user value]
*********************************************************************************************************************************************************
ok: [10.3.134.4] => {
"msg": "the user value is www"
}
ok: [10.3.134.5] => {
"msg": "the user value is www"
}
PLAY RECAP
**************************************************************************************************************************************************************************
10.3.134.4 : ok=2 changed=0 unreachable=0 failed=0
10.3.134.5 : ok=2 changed=0 unreachable=0 failed=0
同時(shí)使用劇本變量和資產(chǎn)變量
取消全局變量丁侄,發(fā)現(xiàn)劇本變量的優(yōu)先級(jí)要高于資產(chǎn)變量的優(yōu)先級(jí)惯雳。
# ansible-playbook priority.yml
PLAY [a play example]
***************************************************************************************************************************************************************
TASK [Gathering Facts]
**************************************************************************************************************************************************************
ok: [10.3.134.4]
ok: [10.3.134.5]
// 打印的 user 值 為mysql , 劇本變量生效
TASK [print the user value]
*********************************************************************************************************************************************************
ok: [10.3.134.4] => {
"msg": "the user value is mysql"
}
ok: [10.3.134.5] => {
"msg": "the user value is mysql"
}
PLAY RECAP
**************************************************************************************************************************************************************************
10.3.134.4 : ok=2 changed=0 unreachable=0 failed=0
10.3.134.5 : ok=2 changed=0 unreachable=0 failed=0
只是用資產(chǎn)變量的情況
不使用全局變量、且注釋掉劇本變量后鸿摇,資產(chǎn)變量才最終生效石景。
---
- name: test variable priority
hosts: all
remote_user: root
#vars:
# user: mysql
tasks:
- name: print the user value
debug: msg='the user value is {{ user }}'
# ansible-playbook priority.yml
PLAY [a play example]
***************************************************************************************************************************************************************
TASK [Gathering Facts]
**************************************************************************************************************************************************************
ok: [10.3.134.4]
ok: [10.3.134.5]
// 打印的 user 值 為tomcat , 資產(chǎn)變量生效。
TASK [print the user value]
*********************************************************************************************************************************************************
ok: [10.3.134.4] => {
"msg": "the user value is tomcat"
}
ok: [10.3.134.5] => {
"msg": "the user value is tomcat"
}
PLAY RECAP
**************************************************************************************************************************************************************************
10.3.134.4 : ok=2 changed=0 unreachable=0 failed=0
10.3.134.5 : ok=2 changed=0 unreachable=0 failed=0
變量?jī)?yōu)先級(jí)結(jié)論
當(dāng)一個(gè)變量同時(shí)在全局變量拙吉、劇本變量和資產(chǎn)變量中定義時(shí)潮孽,優(yōu)先級(jí)最高的是全局變量;其次是劇本變量筷黔;最后才是資產(chǎn)變量往史。