1、playbook簡介html
ansiblie的任務配置文件被稱爲playbook,俗稱「劇本」,每個劇本(playbook)中都包含了一系列的任務,這每一個任務在ansible中又被稱爲「戲劇」(play),一個劇本中包含多出戲劇。。python
前文咱們瞭解了ansible有兩種執行方式ad-hoc和ansible-playbook,ad-hoc主要用於臨時命令的執行,而playbook咱們能夠理解爲ad-hoc的集合,有點相似shell腳本,ad-hoc就至關於shell腳本里的某條任務語句,playbook就至關於整個shell腳本。playbook是由一個或多個「play」組成的列表,play的主要功能在於將預約義的一組主機,裝扮成事先經過ansible中的task定義好的角色。task實際是調用ansible的一個模塊,將多個play組織在一個playbook中,便可以讓他們聯合起來,按事先編排的機制執行預約義的動做。web
如以上圖示,用戶能夠把多條任務(ad-hoc任務)寫到playbook中,用戶用ansible-playbook命令調用執行編排好的playbook,ansible會讀取playbook中的每一條play和task,並按照playbook中的順序從上至下依次執行,ansible會調用每一個task中定義的模塊去依次執行相應的任務,並按照playbook中指定的主機去主機清單裏匹配對應的主機,而後經過ssh認證,把編譯好的相應的任務文件發送到對應的主機或網絡設備上執行,最後返回執行的狀態。shell
2、YAML簡介apache
playbook採用yaml語言編寫,yaml是一個可讀性高的用來表達資料序列格式的語言,它參考了其餘不少種語言,包括:XML、C語言、python、perl以及電子郵箱格式RFC2822等。Clark Evans在2001年首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。YAML( YAML Ain't Markup Language),即yaml不是標記語言。不過在開發這種語言時,yaml的意思實際上是:"Yet Another Markup Language"(還是一種標記語言)安全
ymal特性bash
1)YAML的可讀性好網絡
2)YAML和腳本語言的交互性好數據結構
3)YAML使用實現語言的數據類型app
4)YAML有一個一致的信息模板
5)YAML易於實現,能夠基於流程處理,表達能力強,擴展性好
更多的內容及規範請參考官方文檔http://www.yaml.org
3、playbook語法簡介
1)須要以「---」(3個減號)開始,且需頂行首寫。另外還有選擇性的連續三個點號(...)用來表示文件的結尾。
2)次行開始正常寫playbook的內容,建議次行寫該playbook的功能,固然不寫也是能夠的。
3)使用「#」號註釋代碼。
4)縮進必須統一,不能空格tab混用。
5)縮進的級別必須是一致的,一樣的縮進表明一樣級別,程序判別配置的級別是經過縮進結合換行來實現的。
6)YAML文件內容和Linux系統大小寫判斷方式一直,區分大小寫(大小寫敏感),k/v的值均大小寫敏感。
7)k/v的值可同行寫也可換行寫。同行使用「:」分隔,換行寫須要以「-」分隔。
8)v能夠是字符串,也能夠另一個列表,固然也能夠是字典。
9)一個完整的代碼塊功能最少須要有name:xxx(對任務的描述)。
10)一個name只能包括一個task
11)yaml文件擴展名一般爲yml或yaml
list:列表,其全部元素均使用「-」開頭
示例:
--- # A list of tasty fruits - apple - orange - strawberry - mango ~
dictionary:字典,一般由多個key與value構成
示例:
--- #An employee record name: example developer job: developer skill: elite
固然也能夠將key:value放置於{}中進行表示,用「,」分隔多個key:value
示例:
--- #An employee record {name: example developer,job: developer, skill: elite} ~
YAML的語法和其餘高階語言相似,而且能夠簡單表達清單、散列表、標量等數據結構。其結構(Structure)經過空格來展現,序列(Sequence)裏的項用"-"來表明,Map裏的鍵值對用":"分隔。
示例:
--- name: John Smith age: 41 gender: Male spouse: name: Jane Smith age: 37 gender: Female children: - name: Jimmy Smith age: 17 gender: Male - name: Jenny Smith age: 13 gender: Female ~
4、playbook核心元素
1)hosts :指定執行任務的遠程主機列表(主機清單定義的主機組或單個主機,支持前面的說的主機模式匹配)
2)tasks :任務集
3)varniables :內置變量或自定義變量在playbook中調用
4)templates :模板,可替換模板文件中的變量並實現一些簡單邏輯的文件
5)handlers 和 notity結合使用,由特定條件出發的操做,知足條件方纔執行,不然不執行
6)tags標籤 :給指定的任務貼上標籤,咱們在執行playbook的時候能夠根據標籤選擇性的挑選部分代碼執行,如 ansible-playbook -t tagsname useradd.yml ,這條命令的意思就是在useradd.yml中挑選標籤名爲tagsname的任務執行
5、playbook基礎組件
1)hosts:
playbook中的每個play的目的都是爲了讓特定主機以某個指定的用戶身份執行任務。hosts用於指定要執行任務的主機,須事先定義在主機清單中。hosts指定主機的形式一樣支持像主機清單中定義的那樣,支持通配,支持主機模式匹配與或非,支持IP地址,固然也支持混合匹配與或非。
示例:在websers組,但再也不dbsers組,能夠這樣定義hosts
--- - hosts: websers:!dbsers
2)remote_user:可用於host和task中,也能夠經過指定其經過sudo的方式在遠程執行任務,其可用於play全局或某個任務;此外,甚至能夠在sudo時使用用sudo_user指定sudo時切換的用戶,以下所示
--- - hosts: websers:!dbsers remote_user: root tasks: - name: test connection ping: remote_user: qiuhom sudo: yes sudo_user: qiuping
說明:默認sudo 爲root,上例指定了sudo_user 爲qiuping,上述任務同sudo -u qiuping ping xxxx(表明某主機)命令同樣的意思,固然在使用sudo 時 咱們還須要在目標主機上對qiuhom受權,要讓qiuhom這個用戶具備表明qiuping的權限去執行ping命令。
3)task列表和action:play的主體部分是task list,task list 中的各任務按次序逐個在hosts中指定的全部主機上執行,即在全部主機上完成第一個任務後,再開始第二個任務;task的目的是使用指定的參數執行模塊,而在模塊參數中可使用變量,模塊執行時冪等的,這意味着屢次執行時安全的,意味其結果均一致;每一個task都應該有其name,用於playbook的執行結果輸出,建議其內容能清晰地描述任務步驟,如爲提供name,則action的結果將用於輸出。
tasks:任務列表,它有兩種格式以下
(1)action: module arguments
(2)module: arguments ##建議使用
注意:shell模塊和command模塊後面跟的是命令,而非key=value
若是某項任務的狀態在運行後爲changed時,可經過「notify」通知給相應的handlers;固然任務能夠經過「tags」打標籤,可在ansible-playbook命令上使用-t指定進行調用。
示例:
[qiuhom@test ~]$cat test.yml --- - hosts: websers:!dbsers remote_user: root tasks: - name: test connection ping: remote_user: qiuhom sudo: yes sudo_user: qiuping tags: test - name: test command shell: /bin/ls /home/qiuhom/ [qiuhom@test ~]$ansible-playbook -t test test.yml
說明:用-t 指定標籤名,表示只運行表情所在的任務。
若是命令或腳本的推出碼不爲零,可用使用以下方式忽略或跳過繼續執行如下代碼
--- - hosts: websers:!dbsers remote_user: root tasks: - name: run this command and ignore the result shell: /usr/sbin/ip addr show eth0 || /bin/true - name: run this command and ignore the result shell: /usr/sbin/ip addr show eth0 ignore_errors: True
說明:兩種方式均可以跳過出錯的命令而不打斷playbook,繼續執行如下的代碼,前者使用的短路或的特性,後者使用ignore_errors參數來控制
6、playbook運行的方式
ansible-playbook <filename.yml> ... [options]
經常使用選項:
-C , --check : 只檢查可能會發生的改變,但不真正執行操做,至關於空跑一邊playbook,測試下是否和本身預想的結果同樣,但它不會真正的去遠端主機執行。經常使用語測試寫的playbook語法是否有誤。
--list-hosts :列出playbook指定運行任務所匹配的主機
--list-tags :列出playbook中全部tag名稱
--list-tasks :列出playbook中全部任務名稱
--limit 主機列表 :只針對指定主機列表中的主機執行當前playbook
-v,-vv,-vvv : 顯示執行playbook的過程,-v,顯示較簡單,-vv顯示較詳細,-vvv顯示整個過程(很是詳細)
[root@test ~]#cat test.yml --- - hosts: websers remote_user: root tasks: - name: run this command shell: hostname tags: hostname ignore_errors: True - name: show ip addr shell: /sbin/ip addr show tags: showip [root@test ~]#ansible-playbook test.yml --list-hosts playbook: test.yml play #1 (websers): websers TAGS: [] pattern: [u'websers'] hosts (2): 192.168.0.128 192.168.0.218 [root@test ~]#ansible-playbook test.yml --list-tags playbook: test.yml play #1 (websers): websers TAGS: [] TASK TAGS: [hostname, showip] [root@test ~]#ansible-playbook test.yml --list-tasks playbook: test.yml play #1 (websers): websers TAGS: [] tasks: run this command TAGS: [hostname] show ip addr TAGS: [showip] [root@test ~]#ansible-playbook test.yml --limit 192.168.0.218 PLAY [websers] ******************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************ ok: [192.168.0.218] TASK [run this command] *********************************************************************************************** changed: [192.168.0.218] TASK [show ip addr] *************************************************************************************************** changed: [192.168.0.218] PLAY RECAP ************************************************************************************************************ 192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible-playbook test.yml --limit 192.168.0.218 -v Using /etc/ansible/ansible.cfg as config file PLAY [websers] ******************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************ ok: [192.168.0.218] TASK [run this command] *********************************************************************************************** changed: [192.168.0.218] => {"changed": true, "cmd": "hostname", "delta": "0:00:00.002139", "end": "2019-11-16 23:11:02.996962", "rc": 0, "start": "2019-11-16 23:11:02.994823", "stderr": "", "stderr_lines": [], "stdout": "localhost.localdomain", "stdout_lines": ["localhost.localdomain"]} TASK [show ip addr] *************************************************************************************************** changed: [192.168.0.218] => {"changed": true, "cmd": "/sbin/ip addr show", "delta": "0:00:00.002604", "end": "2019-11-16 23:11:03.733004", "rc": 0, "start": "2019-11-16 23:11:03.730400", "stderr": "", "stderr_lines": [], "stdout": "1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN \n link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n inet 127.0.0.1/8 scope host lo\n inet6 ::1/128 scope host \n valid_lft forever preferred_lft forever\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\n link/ether 00:0c:29:e8:f6:7b brd ff:ff:ff:ff:ff:ff\n inet 192.168.0.218/24 brd 192.168.0.255 scope global eth0\n inet6 fe80::20c:29ff:fee8:f67b/64 scope link \n valid_lft forever preferred_lft forever\n3: pan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN \n link/ether d2:7a:38:cf:27:60 brd ff:ff:ff:ff:ff:ff", "stdout_lines": ["1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN ", " link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00", " inet 127.0.0.1/8 scope host lo", " inet6 ::1/128 scope host ", " valid_lft forever preferred_lft forever", "2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000", " link/ether 00:0c:29:e8:f6:7b brd ff:ff:ff:ff:ff:ff", " inet 192.168.0.218/24 brd 192.168.0.255 scope global eth0", " inet6 fe80::20c:29ff:fee8:f67b/64 scope link ", " valid_lft forever preferred_lft forever", "3: pan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN ", " link/ether d2:7a:38:cf:27:60 brd ff:ff:ff:ff:ff:ff"]} PLAY RECAP ************************************************************************************************************ 192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#
說明:--limit 所指定的主機必須是在playbook中說指定的主機範圍內。
7、playbook vs shell scripts
1)shell腳本以下:
#!/bin/bash # 安裝Apache yum install --quiet -y httpd # 複製配置文件 cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf cp/tmp/vhosts.conf /etc/httpd/conf.d/ # 啓動Apache,並設置開機啓動 service httpd start chkconfig httpd on
2)playbook
--- - hosts: websers remote_user: root tasks: - name: create apache group group: name=apache gid=80 system=yes - name: create apache user user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html - name: install httpd yum: name=httpd - name: copy config file copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/ - name: copy config 2 file copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/ - name: start httpd service service: name=httpd state=started enabled=yes
說明:二者都是實現一樣的目的,很明顯playbook的優點要比腳本的優點多,playbook 能夠針對不少臺主機進行任務執行,而腳本只能夠在某一臺主機上執行;腳本重複執行沒有冪等性,頗有可能帶來不少錯誤,而playbook卻不會有這樣的苦惱。