Playbook的用法
目錄
Playbook
?Playbook 與 Ad-Hoc 對(duì)比
YAML 語(yǔ)言特性
YAML語(yǔ)法簡(jiǎn)介
支持的數(shù)據(jù)類型? ?
寫(xiě)法格式??
1 scalar 標(biāo)量? 建議縮進(jìn)兩個(gè)空格,可多
2 Dictionary 字典
3 List 列表
三種常見(jiàn)的數(shù)據(jù)格式
?Playbook 核心組件? 不要用 tab 可以#注釋
hosts
remote_user 組件? ?指定賬戶默認(rèn)root
nginx安裝?#默認(rèn)會(huì)去files文件里找 把文件放里面不用加前面的
?性能優(yōu)化
方法1
?方法2
register 注冊(cè)變量
在主機(jī)清單中定義主機(jī)和主機(jī)組的變量
變量的優(yōu)先級(jí)從高到低如下
?Template 模板
jinja2語(yǔ)言
template? ? 專門(mén)存放模板文件
?template中使用流程控制 for 和 if
for 循環(huán)
?if 條件判斷
?使用循環(huán)迭代
迭代 loop (with_items)
until 循環(huán)
with_lines 逐行處理?
條件判斷 when
分組 block
關(guān)閉 changed 狀態(tài)
利用 changed_when 檢查task返回結(jié)果
滾動(dòng)執(zhí)行
?委派至其它主機(jī)執(zhí)行
只執(zhí)行一次
環(huán)境變量?
Yaml 文件的相互調(diào)用
import_playbook??由一個(gè)yml統(tǒng)一調(diào)用
Roles 角色
roles目錄結(jié)構(gòu):?
Roles各目錄作用
Playbook
- ?一個(gè) playbook(劇本)文件是一個(gè)YAML語(yǔ)言編寫(xiě)的文本文件
- 通常一個(gè)playbook只包括一個(gè)play ,但可以包括多個(gè)Play
- 一個(gè) play的主要包括兩部分: 主機(jī)和tasks. 即實(shí)現(xiàn)在指定一組主機(jī)上執(zhí)行一個(gè)tasks定義好的任務(wù)列 表。
- 一個(gè)tasks中可以有一個(gè)或多個(gè)task任務(wù) 每一個(gè)Task本質(zhì)上就是調(diào)用ansible的一個(gè)module
- 在復(fù)雜場(chǎng)景中,一個(gè)playbook中也可以包括多個(gè)play,實(shí)現(xiàn)對(duì)多組不同的主機(jī)執(zhí)行不同的任務(wù)
?Playbook 與 Ad-Hoc 對(duì)比
- Playbook是對(duì)多個(gè) AD-Hoc 的一種編排組合的實(shí)現(xiàn)方式
- Playbook能控制任務(wù)執(zhí)行的先后順序
- Playbook可以持久保存到文件中從而方便多次調(diào)用運(yùn)行,而Ad-Hoc只能臨時(shí)運(yùn)行。
- Playbook適合復(fù)雜的重復(fù)性的任務(wù),而Ad-Hoc適合做快速簡(jiǎn)單的一次性任務(wù)
YAML 語(yǔ)言特性
- YAML的可讀性好
- YAML和腳本語(yǔ)言的交互性好
- YAML使用實(shí)現(xiàn)語(yǔ)言的數(shù)據(jù)類型
- YAML有一個(gè)一致的信息模型
- YAML易于實(shí)現(xiàn)
- YAML可以基于流來(lái)處理
- YAML表達(dá)能力強(qiáng),擴(kuò)展性好?
YAML語(yǔ)法簡(jiǎn)介
- 在單一文件第一行,用連續(xù)三個(gè)連字號(hào)"-" 開(kāi)始,還有選擇性的連續(xù)三個(gè)點(diǎn)號(hào)( ... )用來(lái)表示文件的結(jié) 尾
- 次行開(kāi)始正常寫(xiě)Playbook的內(nèi)容,一般建議寫(xiě)明該P(yáng)laybook的功能
- 使用#號(hào)注釋代碼
- 縮進(jìn)的級(jí)別也必須是一致的,同樣的縮進(jìn)代表同樣的級(jí)別,程序判別配置的級(jí)別是通過(guò)縮進(jìn)結(jié)合換 行來(lái)實(shí)現(xiàn)的
- 縮進(jìn)不支持tab,必須使用空格進(jìn)行縮進(jìn)
- 縮進(jìn)的空格數(shù)不重要,只要相同層級(jí)的元素左對(duì)齊即可
- YAML文件內(nèi)容是區(qū)別大小寫(xiě)的,key/value的值均需大小寫(xiě)敏感
- 多個(gè)key/value可同行寫(xiě)也可換行寫(xiě),同行使用,分隔
- key后面冒號(hào)要加一個(gè)空格 比如: key: value value可是個(gè)字符串,也可是另一個(gè)列表
- YAML文件擴(kuò)展名通常為yml或yaml?
支持的數(shù)據(jù)類型? ?
YAML 支持以下常用幾種數(shù)據(jù)類型:
- 標(biāo)量:單個(gè)的、不可再分的值
- 對(duì)象:鍵值對(duì)的集合,又稱為: 字典(dictionary)/ 哈希(hashes) / 映射(mapping)
- 數(shù)組:一組按次序排列的值,又稱為: 列表(list)/ 序列(sequence)?
寫(xiě)法格式??
1 scalar 標(biāo)量? 建議縮進(jìn)兩個(gè)空格,可多
key對(duì)應(yīng)value
name: wang
age: 18
使用縮進(jìn)的方式
name:
?wang
age:
?18
2 Dictionary 字典
格式
格式
使用縮進(jìn)方式
account:
????????name: wang
????????age: 18
????????gender: male?
范例:
#不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite(社會(huì)精英)
#同一行,也可以將key:value放置于{}中進(jìn)行表示,用,分隔多個(gè)key:value
# An employee record
{name: "Example Developer", job: "Developer", skill: "Elite"}?
3 List 列表
列表由多個(gè)元素組成, 本質(zhì)就是數(shù)組
每個(gè)元素放在不同行,每個(gè)元素一行,且元素前均使用中橫線 - 開(kāi)頭,并且中橫線 - 和元素之間有一個(gè)空
格
也可以將所有元素用 [ ] 括起來(lái)放在同一行,每個(gè)元素之間用逗號(hào)分隔?
格式
course: [ linux , golang , python ]?
也可以寫(xiě)成以 - 開(kāi)頭的多行
course:
????????- linux
????????- golang
????????- python?
元素里也可以包含字典
course:
??? ? - linux: manjaro
????????price: 10000
???? ?- golang: gin
????????class: 49
??? ? - python: django?
范例:
#不同行,行以-開(kāi)頭,后面有一個(gè)空格
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#同一行
[Apple,Orange,Strawberry,Mango]?
范例:YAML 表示一個(gè)家庭
name: John Smith
age: 41
gender: Male
spouse: { name: Jane Smith, age: 37, gender: Female } # 寫(xiě)在一行里
?????
? ?name: Jane Smith #也可以寫(xiě)成多行
????????age: 37
????????gender: Female
children: [ {name: Jimmy Smith,age: 17, gender: Male}, {name: Jenny Smith, age:
13, gender: Female}, {name: hao Smith, age: 20, gender: Male } ] #寫(xiě)在一行
?? ? ?- name: Jimmy Smith #寫(xiě)在多行,更為推薦的寫(xiě)法
????????age: 17
????????gender: Male
??? ? - {name: Jenny Smith, age: 13, gender: Female}
??????- {name: hao Smith, age: 20, gender: Male }?
三種常見(jiàn)的數(shù)據(jù)格式
- XML:Extensible Markup Language,可擴(kuò)展標(biāo)記語(yǔ)言,可用于數(shù)據(jù)交換和配置
- JSON:JavaScript Object Notation, JavaScript 對(duì)象表記法,主要用來(lái)數(shù)據(jù)交換或配置,不支持注 釋
- YAML:YAML Ain't Markup Language YAML 不是一種標(biāo)記語(yǔ)言, 主要用來(lái)配置,大小寫(xiě)敏感, 不支持tab
可以用工具互相轉(zhuǎn)換,參考網(wǎng)站:?JSON在線解析及格式化驗(yàn)證 - JSON.cn
定義的組在
#vim /etc/ansible/hosts [webservers] #最下面 在vim里 按G 跳到最下面 10.0.0.8 10.0.0.18 [dbservers] 10.0.0.18 10.0.0.[101:102]Playbook 核心組件? 不要用 tab 可以#注釋
一個(gè)playbook 中由多個(gè)組件組成,其中所用到的常見(jiàn)組件類型如下:
- Hosts 執(zhí)行的遠(yuǎn)程主機(jī)列表
- Tasks 任務(wù)集,由多個(gè)task的元素組成的列表實(shí)現(xiàn),每個(gè)task是一個(gè)字典,一個(gè)完整的代碼塊功能需最 少元素需包括 name 和 task,一個(gè)name只能包括一個(gè)task
- Variables 內(nèi)置變量或自定義變量在playbook中調(diào)用
- Templates 模板,可替換模板文件中的變量并實(shí)現(xiàn)一些簡(jiǎn)單邏輯的文件
- Handlers 和 notify 結(jié)合使用,由特定條件觸發(fā)的操作,滿足條件方才執(zhí)行,否則不執(zhí)行
- tags 標(biāo)簽 指定某條任務(wù)執(zhí)行,用于選擇運(yùn)行playbook中的部分代碼。ansible具有冪等性,因此 會(huì)自動(dòng)跳過(guò)沒(méi)有變化的部分,即便如此,有些代碼為測(cè)試其確實(shí)沒(méi)有發(fā)生變化的時(shí)間依然會(huì)非常地 長(zhǎng)。此時(shí),如果確信其沒(méi)有變化,就可以通過(guò)tags跳過(guò)此些代碼片斷?
常用 簡(jiǎn)介
--syntax,--syntax-check #語(yǔ)法檢查,功能相當(dāng)于bash -n -C --check #模擬執(zhí)行dry run ,只檢測(cè)可能會(huì)發(fā)生的改變,但不真正執(zhí)行操作 --list-hosts #列出運(yùn)行任務(wù)的主機(jī) --list-tags #列出tag --list-tasks #列出task --limit 主機(jī)列表 #只針對(duì)主機(jī)列表中的特定主機(jī)執(zhí)行 ansible-playbook --limit 10.0.0.8 nginx.yaml -i INVENTORY, --inventory INVENTORY #指定主機(jī)清單文件,通常一個(gè)項(xiàng)對(duì)應(yīng)一個(gè)主機(jī)清單文件 --start-at-task START_AT_TASK #從指定task開(kāi)始執(zhí)行,而非從頭開(kāi)始,START_AT_TASK為任務(wù)的 name -v -vv -vvv #顯示過(guò)程vim hello.yaml?
--- 不強(qiáng)制寫(xiě) # 第一個(gè)Playbook 文件- hosts: webservers #針對(duì)的主機(jī) 可多個(gè)tasks: #針對(duì)的任務(wù)- name: test ping #這個(gè)任務(wù)做什么的 可漢字ping: #有參數(shù)可以寫(xiě) 沒(méi)有就這樣- name: shell pwd #做什么shell: 'hostname -I' #命令及參數(shù)ansible-playbook -C hello.yaml? ? ?#模擬執(zhí)行檢查
ansible-playbook --syntax-check hello.yaml? ? ? ? ? ? #語(yǔ)法檢查
[root@ubuntu2004 ~]#ansible-playbook -vv hello.yaml? ? ?#-v查看信息 最多4個(gè) 可以不加
hosts
組件 Hosts:playbook中的每一個(gè)play的目的都是為了讓特定主機(jī)以某個(gè)指定的用戶身份執(zhí)行任務(wù)。hosts用 于指定要執(zhí)行指定任務(wù)的主機(jī),須事先定義在主機(jī)清單中
one.example.com one.example.com:two.example.com 192.168.1.50 192.168.1.* webservers:dbservers #或者,兩個(gè)組的并集 webservers:&dbservers #與,兩個(gè)組的交集 webservers:!dbservers #在webservers組,但不在dbservers組 案例 - hosts: webservers:appserversremote_user 組件? ?指定賬戶默認(rèn)root
remote_user: 可用于Host和task中。也可以通過(guò)指定其通過(guò)sudo的方式在遠(yuǎn)程主機(jī)上執(zhí)行任務(wù),其可 用于play全局或某任務(wù);此外,甚至可以在sudo時(shí)使用sudo_user指定sudo時(shí)切換的用戶?
- hosts: webserversremote_user: roottasks:- name: test connectionping:remote_user: wangesudo: yes #默認(rèn)sudo為rootsudo_user:wang #將wange用戶sudo為wangnginx安裝?#默認(rèn)會(huì)去files文件里找 把文件放里面不用加前面的
--- # nginx - hosts: 10.0.0.8remote_user: roottasks:- name: 安裝yum:name: nginxstate: present- name: 復(fù)制copy:src: /data/nginx.conf #默認(rèn)會(huì)去files文件里找 把文件放里面不用加前面的 dest: /etc/nginx/nginx.conf 也是- name: 頁(yè)面copy:src: /data/index.htmldest: /usr/share/nginx/html/index.html- name: 啟動(dòng)service:name: nginxstate:startedenabled: yesAnsible facts簡(jiǎn)介? 修改收集加速
大家肯定疑問(wèn),這個(gè)facts是個(gè)啥?
facts組件是Ansible用于采集被管理機(jī)器設(shè)備信息的一個(gè)功能,采集的機(jī)器設(shè)備信息主要包含IP地址,操作系統(tǒng),以太網(wǎng)設(shè)備,mac 地址,時(shí)間/日期相關(guān)數(shù)據(jù),硬件信息等。
那話又說(shuō)回來(lái)了,采集這些信息有什么用呢?有的時(shí)候我們需要根據(jù)遠(yuǎn)程主機(jī)的信息作為執(zhí)行條件操作,例如,根據(jù)遠(yuǎn)程服務(wù)器使用的操作系統(tǒng)版本,可以安裝不同版本的軟件包;或者也可以顯示與每臺(tái)遠(yuǎn)程計(jì)算機(jī)相關(guān)的一些信息,例如每臺(tái)設(shè)備上有多少RAM可用。
所以,在一些業(yè)務(wù)場(chǎng)景中,facts對(duì)我們是很有幫助的,省去了我們好多工作,大大提高了工作效率。
性能優(yōu)化
每次執(zhí)行playbook,默認(rèn)會(huì)收集每個(gè)主機(jī)的所有facts變量,將會(huì)導(dǎo)致速度很慢,可以采用下面方法加速
方法1
關(guān)閉facts采集加速執(zhí)行,此方法將導(dǎo)致無(wú)法使用facts變量
- hosts: all
gather_facts: no
?方法2
當(dāng)使用 gather_facts: no 關(guān)閉 facts,確實(shí)能加速 Ansible 執(zhí)行,但是有時(shí)候又需要使用 facts 中的內(nèi)容,還希望執(zhí)行的速度快,這時(shí)候可以設(shè)置facts 的緩存,將facts變量信息存在redis服務(wù)器中
[root@ansible ~]# cat /etc/ansible/ansible.cfg
[defaults]
# smart 表示默認(rèn)收集 facts,但 facts 已有的情況下不會(huì)收集,即使用緩存 facts
# implicit 表示默認(rèn)收集 facts,要禁止收集,必須使用 gather_facts: False
# explicit 則表示默認(rèn)不收集,要顯式收集,必須使用gather_facts: True
gathering = smart ??????????????????????????? #在使用 facts 緩存時(shí)設(shè)置為smart
fact_caching_timeout = 86400???????? #緩存時(shí)長(zhǎng)
fact_caching = redis???????? ????????????????#緩存存在redis中
fact_caching_connection = 10.0.0.100:6379:0 ????????#0表示redis的0號(hào)數(shù)據(jù)庫(kù)
#若redis設(shè)置了密碼
fact_caching_connection = 10.0.0.100:6379:0:password
ignore_errors? ?暫時(shí)忽略錯(cuò)誤
在playbook執(zhí)行的過(guò)程中,難免會(huì)遇到一些錯(cuò)誤。由于playbook遇到錯(cuò)誤后,不會(huì)執(zhí)行之后的任務(wù),不便于調(diào)試,此時(shí),可以使用ignore_errors來(lái)暫時(shí)忽略錯(cuò)誤,使得playbook繼續(xù)執(zhí)行。
ignore_errors: yes #執(zhí)行忽略上面錯(cuò)誤 True 一樣register 輸出成變量 比如用debug模塊進(jìn)行顯示輸出?
在playbook中可以使用register將捕獲命令的輸出保存在臨時(shí)變量中,方便后續(xù)調(diào)用此變量,比如可以使用debug模塊進(jìn)行顯示輸出?
[root@centos8 ~]#cat register1.yml - hosts: dbserverstasks:- name: get variableshell: hostnameregister: name- name: "print variable"debug:msg: "{{ name }}" #輸出register注冊(cè)的name變量的全部信息,注意 變量要加" "引起來(lái)#msg: "{{ name.cmd }}" #顯示命令#msg: "{{ name.rc }}" #顯示命令成功與否#msg: "{{ name.stdout }}" #顯示命令的輸出結(jié)果為字符串形式,所有結(jié)果都放 在一行里顯示,適合于結(jié)果是單行輸出#msg: "{{ name.stdout_lines }}" #顯示命令的輸出結(jié)果為列表形式,逐行標(biāo)準(zhǔn)輸出,適 用于多行顯示#msg: "{{ name['stdout_lines'] }}" #顯示命令的執(zhí)行結(jié)果為列表形式,和效果上面相同#msg: "{{ name.stdout_lines[0] }}" #顯示命令的輸出結(jié)果的列表中的第一個(gè)元素#說(shuō)明 第一個(gè) task 中,使用了 register 注冊(cè)變量名為 name ;當(dāng) shell 模塊執(zhí)行完畢后,會(huì)將數(shù)據(jù)放到該 變量中。 第二給 task 中,使用了 debug 模塊,并從變量name中獲取數(shù)據(jù)。 [root@centos8 ~]#ansible-playbook register1.yml - hosts: webserverstasks:- name: get variableshell: hostnameregister: name- name: "print variable"debug:#msg: "{{ name }}"msg: "{{ name.stdout_lines }}"Playbook中使用handlers和notify??觸發(fā)器 指定觸發(fā)
Handlers本質(zhì)是task list ,類似于MySQL中的觸發(fā)器觸發(fā)的行為,其中的task與前述的task并沒(méi)有本質(zhì) 上的不同,只有在關(guān)注的資源發(fā)生變化時(shí),才會(huì)采取一定的操作。
Notify對(duì)應(yīng)的action 在所有task都執(zhí)行完才會(huì)最后被觸發(fā),這樣可避免多個(gè)task多次改變發(fā)生時(shí)每次都 觸發(fā)執(zhí)行指定的操作,Handlers僅在所有的變化發(fā)生完成后一次性地執(zhí)行指定操作。
在notify中列出的操作稱為handler,也即notify中調(diào)用handler中定義的操作
- 如果多個(gè)task通知了相同的handlers, 此handlers僅會(huì)在所有task結(jié)束后運(yùn)行一 次。
- 只有notify對(duì)應(yīng)的task發(fā)生改變了才會(huì)通知handlers, 沒(méi)有改變則不會(huì)觸發(fā)handlers
- handlers 是在所有前面的tasks都成功執(zhí)行才會(huì)執(zhí)行,如果前面任何一個(gè)task失敗,會(huì)導(dǎo)致handler跳 過(guò)執(zhí)行
列:?
# nginx - hosts: 10.0.0.8tasks:- name: 安裝yum:name: nginxstate: present- name: 復(fù)制copy:src: /data/nginx.confdest: /etc/nginx/nginx.confnotify: restart nginx # 注釋 上下一樣的名字 預(yù)示著這里改變就執(zhí)行下面的命令 不變不執(zhí)行 - name: 頁(yè)面copy:src: /data/index.htmldest: /usr/share/nginx/html/index.html- name: 啟動(dòng)service:name: nginxstate:startedenabled: yeshandlers:- name: restart nginx # 注釋 上下一樣的名字 最好別漢語(yǔ)又可能出問(wèn)題service: name=nginx state=restartedforce_handlers? ? ?不論前面的task成功與否 都執(zhí)行
如果不論前面的task成功與否,都希望handlers能執(zhí)行, 可以使用force_handlers: yes 強(qiáng)制執(zhí)行handler 范例: 強(qiáng)制調(diào)用handlers\
- hosts: webserversforce_handlers: yes #無(wú)論task中的任何一個(gè)task失敗,仍強(qiáng)制調(diào)用handlerstasks:- name: config filecopy: src=nginx.conf dest=/etc/nginx/nginx.confnotify: restart nginx- name: install packageyum: name=no_exist_packagehandlers:- name: restart nginxservice: name=nginx state=restartedPlaybook中使用tags組件
- 默認(rèn)情況下, Ansible 在執(zhí)行一個(gè) playbook 時(shí),會(huì)執(zhí)行 playbook 中所有的任務(wù)
- 在playbook文件中,可以利用tags組件,為特定 task 指定標(biāo)簽,當(dāng)在執(zhí)行playbook時(shí),可以只執(zhí)行特 定tags的task,而非整個(gè)playbook文件
- 可以一個(gè)task對(duì)應(yīng)多個(gè)tag,也可以多個(gè)task對(duì)應(yīng)同一個(gè)tag
- 還有另外3個(gè)特殊關(guān)鍵字用于標(biāo)簽, tagged, untagged 和 all,它們分別是僅運(yùn)行已標(biāo)記,只有未標(biāo)記和所 有任務(wù)。
?
在主機(jī)清單中定義主機(jī)和主機(jī)組的變量
[webservers]
10.0.0.101 host=web01
10.0.0.102 host=web02
[webservers:vars]
domain=wang
[appservers]
10.0.0.[7:8]
10.0.0.101
[all:vars]
suffix=edu
?
?
?
?2
?將變量放在文件里,不放在變量也行
變量的優(yōu)先級(jí)從高到低如下
-e 選項(xiàng)定義變量 -->playbook中vars_files --> playbook中vars變量定義 -->host_vars/主機(jī)名
文件 -->主機(jī)清單中主機(jī)變量--> group_vars/主機(jī)組名文件-->group_vars/all文件--> 主機(jī)清單組變量
?Template 模板
模板是一個(gè)文本文件,可以用于根據(jù)每個(gè)主機(jī)的不同環(huán)境而為生成不同的文件
模板文件中支持嵌套jinja2語(yǔ)言的指令,來(lái)實(shí)現(xiàn)變量,條件判斷,循環(huán)等功能
需要使用template模塊實(shí)現(xiàn)文件的復(fù)制到遠(yuǎn)程主機(jī),但和copy模塊不同,復(fù)制過(guò)去的文件每個(gè)主機(jī)可以會(huì)有所不同
jinja2語(yǔ)言
Jinja2 是一個(gè)現(xiàn)代的,設(shè)計(jì)者友好的,仿照 Django 模板的 Python 模板語(yǔ)言。 它速度快,被廣泛使用,并且提供了可選的沙箱模板執(zhí)行環(huán)境保證安全:
特性:
- 沙箱中執(zhí)行
- 強(qiáng)大的 HTML 自動(dòng)轉(zhuǎn)義系統(tǒng)保護(hù)系統(tǒng)免受 XSS
- 模板繼承
- 及時(shí)編譯最優(yōu)的 python 代碼
- 可選提前編譯模板的時(shí)間
- 易于調(diào)試。異常的行數(shù)直接指向模板中的對(duì)應(yīng)行。
- 可配置的語(yǔ)法
template? ? 專門(mén)存放模板文件
template功能:可以根據(jù)和參考模塊文件,動(dòng)態(tài)生成相類似的配置文件
template文件存建議放于templates目錄下,且命名為 .j2 結(jié)尾
yaml/yml 文件和templates目錄平級(jí),此時(shí)playbook中指定模板文件時(shí)可不用指定路徑, 目錄結(jié)構(gòu)如下?
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
template變更替換
#修改文件nginx.conf.j2
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }};? ? ? 本機(jī)的cpu個(gè)數(shù),可以+*等
......
?template中使用流程控制 for 和 if
template中也可以使用流程控制 for 循環(huán)和 if 條件判斷,實(shí)現(xiàn)動(dòng)態(tài)生成文件功能
for 循環(huán)
格式?
{% for i in EXPR %}
...
{% endfor %}
#示例:
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
?for.yam? ? ? ? ?#引用下面
?test.conf.j2
?
?
?#temlnginx2.yml
---
- hosts: webservers
remote_user: root
vars:
nginx_vhosts:
- 81
- 82
- 83
tasks:
- name: template config
template: src=nginx.conf2.j2 dest=/data/nginx.conf
#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
ansible-playbook -C templnginx2.yml --limit 10.0.0.8
#生成的結(jié)果:
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
?循環(huán),提取建網(wǎng)站
?
結(jié)果?
?
?if 條件判斷
有的有server_name有的沒(méi)有if判斷
?
?
?
?使用循環(huán)迭代
迭代:當(dāng)有需要重復(fù)性執(zhí)行的任務(wù)時(shí),可以使用迭代機(jī)制
迭代 loop (with_items)
- 對(duì)迭代項(xiàng)的引用,固定內(nèi)置變量名為"item"
- 要在task中使用with_items給定要迭代的元素列表
- 注意: ansible2.5版本后,可以用loop代替with_items
列表元素格式:
字符串
- 字典 key: value
?類似if循環(huán)
---
- hosts: webservers
remote_user: root
tasks:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
- testuser3
#上面語(yǔ)句的功能等同于下面的語(yǔ)句
- name: add several users
user: name=testuser1 state=present groups=wheel
- name: add several users
user: name=testuser2 state=present groups=wheel
- name: add several users
user: name=testuser3 state=present groups=wheel?
范例: 安裝多個(gè)軟件包?
#方法1 # cat install_packages.yml - hosts: webserverstasks:- name: Installed Httpd Php-fpm Packageyum: name={{ pack }} state=latestvars:pack:- httpd- php-fpm #方法2 # cat install_packages2.yml - hosts: webserverstasks:- name: Installed Httpd Php-fpm Packageyum:name: {{ item }}state: latestloop:- httpd- php-fpm # cat install_packages3.yml --- - hosts:webserversremote_user: roottasks- name: install some packagesyum: name={{ item }} state=presentwith_items:- nginx- memcached- php-fpmuntil 循環(huán)
#until為false時(shí)才會(huì)執(zhí)行循環(huán),為true則退出循環(huán)
[root@ansible ansible]#cat until.yml
- hosts: localhost
gather_facts: false
tasks:
- debug: msg="until"
until: false
retries: 3 #默認(rèn)值即為3次
delay: 1
范例: 以輪詢的方式等待服務(wù)同步完成
- name: 以輪詢的方式等待服務(wù)同步完成
shell: "systemctl is-active mysqld.service"? ? ? ? #執(zhí)行命令
register: mysqld_status? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #結(jié)果保存在在里面
until: '"active" in mysqld_status.stdout'? ? ? ? ? ? ? ? #檢查這里里面是否有,有退出
retries: 8? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #試幾次
delay: 8? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#停頓幾秒
with_lines 逐行處理?
逐行處理,一行打印一次
[root@ansible ansible]#cat with_lines.yml
- hosts: localhost
tasks:
- debug: msg={{ item }}
with_lines: ps aux
條件判斷 when
when語(yǔ)句可以實(shí)現(xiàn)條件測(cè)試。如果需要根據(jù)變量、facts或此前任務(wù)的執(zhí)行結(jié)果來(lái)做為某task執(zhí)行與否的前提時(shí)要用到條件測(cè)試,通過(guò)在task后添加when子句即可使用jinja2的語(yǔ)法格式條件測(cè)試?
范例: 判斷OS版本
[root@ansible ansible]#cat when.yml - hosts: alltasks:- name: install httpdyum:name: "httpd"when:- ansible_distribution_file_variety == "RedHat"- name: install packageapt:name: "apache2"when:- ansible_distribution_file_variety == "Debian"?范例: 數(shù)據(jù)類型轉(zhuǎn)換
- hosts: appserverstasks:- shell: echo "only on Red Hat 6, derivatives, and liter"when: ansible_distribution_file_variety == "RedHat" and ansible_facts['lsb']['major_release'] | int > 7分組 block
當(dāng)想在滿足同樣條件下,執(zhí)行多個(gè)任務(wù)時(shí),就需要分組。而不再針對(duì)每個(gè)任務(wù)都是用
- hosts: appserverstasks:- block:- shell: echo "task1"- shell: echo "task2"when:- ansible_distribution_file_variety == "RedHat"- ansible_facts['lsb']['major_release'] | int > 7關(guān)閉 changed 狀態(tài)
當(dāng)確定某個(gè)task不會(huì)對(duì)被控制端做修改時(shí)但執(zhí)行結(jié)果卻顯示是黃色的changed狀態(tài)
可以通過(guò) changed_when: false 關(guān)閉changed狀態(tài)
執(zhí)行命令完他會(huì)顯示黃,這樣可以顯示綠
[root@ansible ansible]#cat test_changed.yml --- - hosts: webserverstasks:- name: check sshd serviceshell: ps aux| grep sshdchanged_when: false #關(guān)閉changed狀態(tài)利用 changed_when 檢查task返回結(jié)果
changed_when 檢查task返回結(jié)果,決定是否繼續(xù)向下執(zhí)行
滾動(dòng)執(zhí)行
管理節(jié)點(diǎn)過(guò)多導(dǎo)致的超時(shí)問(wèn)題解決方法
默認(rèn)情況下,Ansible將嘗試并行管理playbook中所有的機(jī)器。對(duì)于滾動(dòng)更新用例,可以使用serial關(guān)鍵字定義Ansible一次應(yīng)管理多少主機(jī),還可以將serial關(guān)鍵字指定為百分比,表示每次并行執(zhí)行的主機(jī)數(shù)占總數(shù)的比例
范例:? 一次兩臺(tái)機(jī)器執(zhí)行
#vim test_serial.yml --- - hosts: allserial: 2 #每次只同時(shí)處理2個(gè)主機(jī),將所有task執(zhí)行完成后,再選下2個(gè)主機(jī)再執(zhí)行所有task,直至所 有主機(jī)gather_facts: Falsetasks:- name: task onecommand: hostname- name: task twocommand: hostnamename: test serail
hosts: all
serial: "20%" #每次只同時(shí)處理20%的主機(jī),主機(jī)數(shù)不足時(shí),向下取整?
?委派至其它主機(jī)執(zhí)行
利用委托技術(shù),可以在非當(dāng)前被控主機(jī)的其它主機(jī)上執(zhí)行指定操作
注意: 當(dāng)前執(zhí)行的被管理端主機(jī)需要實(shí)現(xiàn)到被委派主機(jī)的ssh key 驗(yàn)證才能實(shí)現(xiàn)委派
范例: 將任務(wù)委派給指定的主機(jī)執(zhí)行
[root@ansible ansible]#cat delegate.yml #在10.0.0.8上執(zhí)行hostname -I,而非當(dāng)前主機(jī)localhost - hosts: localhosttasks:- name: show ip addresscommand: hostname -Idelegate_to: 10.0.0.8 #指定當(dāng)前任務(wù)被委派給的目標(biāo)主機(jī)delegate_facts: true #收集被委派的目標(biāo)主機(jī)的facts信息范例: 將任務(wù)被委派給控制端ansible主機(jī)執(zhí)行
#在本地執(zhí)行ifconfig,而非10.0.0.8 [root@ansible ansible]#cat delegate2.yml - hosts: 10.0.0.8tasks:- name: show ip addresslocal_action: command ifconfig #被委派給控制端ansible主機(jī)執(zhí)行- name: show hostnameshell: hostnameconnection: local #被委派給控制端ansible主機(jī)執(zhí)行- name: kernel versionshell: hostname -Idelegate_to: localhost #被委派給控制端ansible主機(jī)執(zhí)行run_one: truce #委派任務(wù)只執(zhí)行一次只執(zhí)行一次
利用 run_once 指令可以只執(zhí)行一次,而非在所有被控主機(jī)都執(zhí)行
root@ansible ~]#cat run_once.yml
- hosts: webservers
tasks:
- command: hostname
run_once: true
[root@ansible ~]#ansible-playbook run_once.yml --list-hosts
playbook: run_once.yml
play #1 (webservers): webservers TAGS: []
pattern: ['webservers']
hosts (2):
10.0.0.8
10.0.0.7
[root@ansible ~]#ansible-playbook run_once.yml
環(huán)境變量?
臨時(shí)修改環(huán)境變量,只針對(duì)當(dāng)前動(dòng)作的task有效
[root@ansible ~]#cat environment.yml - hosts: localhosttasks:- shell: echo $PATHenvironment:PATH: /usr/local/app/bin:{{ ansible_env.PATH }} [root@ansible ~]#ansible-playbook environment.yml -vYaml 文件的相互調(diào)用
?include
利用include 或 include_tasks 可以在某個(gè)task中調(diào)用其它的只有task內(nèi)容的yaml文件
import_playbook??由一個(gè)yml統(tǒng)一調(diào)用
還可以將多個(gè)包含完整內(nèi)容的yml文件由一個(gè)yml統(tǒng)一調(diào)用
[root@ansible ansible]#cat main.yml - import_playbook: tasks1.yml - import_playbook: tasks2.yml[root@ansible ansible]#cat tasks1.yml --- - hosts: webserverstasks:- name: run task1 jobcommand: wall run task1 job [root@ansible ansible]#cat tasks2.yml --- - hosts: dbserverstasks:- name: run task2 jobcommand: wall run task2 job [root@ansible ansible]#ansible-play main.ymlRoles 角色
roles:多個(gè)角色的集合目錄, 可以將多個(gè)的role,分別放至roles目錄下的獨(dú)立子目錄中,如下示例
roles/
mysql/
nginx/
tomcat/
redis/
roles目錄結(jié)構(gòu):?
playbook1.yml
playbook2.yml
roles/
project1/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
project2/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
Roles各目錄作用
roles/project/ :項(xiàng)目名稱,有以下子目錄
默認(rèn)找mian.yml
- files/ :存放由copy或script模塊等調(diào)用的文件
- templates/:template模塊查找所需要模板文件的目錄
- tasks/:定義task,role的基本元素,至少應(yīng)該包含一個(gè)名為main.yml的文件;其它的文件需要在此
- 文件中通過(guò)include進(jìn)行包含
- handlers/:至少應(yīng)該包含一個(gè)名為main.yml的文件;此目錄下的其它的文件需要在此文件中通過(guò)include進(jìn)行包含
- vars/:定義變量,至少應(yīng)該包含一個(gè)名為main.yml的文件;此目錄下的其它的變量文件需要在此文件中通過(guò)include進(jìn)行包含,也可以通過(guò)項(xiàng)目目錄中的group_vars/all定義變量,從而實(shí)現(xiàn)角色通用代碼和項(xiàng)目數(shù)據(jù)的分離
- meta/:定義當(dāng)前角色的特殊設(shè)定及其依賴關(guān)系,至少應(yīng)該包含一個(gè)名為main.yml的文件,其它文件需在此文件中通過(guò)include進(jìn)行包含
- defaults/:設(shè)定默認(rèn)變量時(shí)使用此目錄中的main.yml文件,比vars的優(yōu)先級(jí)低?
總結(jié)
以上是生活随笔為你收集整理的Playbook的用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 和平精英美化包
- 下一篇: 解决连接湖南大学校园网Server is