如何Ansible編寫一個Playbook
- 2019 年 11 月 12 日
- 筆記
1、playbooks介紹
playbooks是 一個不同於使用Ansible命令行執行方式的模式,其功能更強大靈活。簡單來說,playbook是一個非常簡單的配置管理和多主機部署系統,不同於任何已經存在的模式,可作為一個適合部署複雜應用程序的基礎。Playbook可以定製配置,可以按照指定的操作步驟有序執行,支持同步和異步方式。值得注意的是playbook是通過YAML格式來進行描述定義的。
2、playbook基礎組件
1.Hosts:運行執行任務(task)的目標主機
2.remote_user:在遠程主機上執行任務的用戶
3.tasks:任務列表
4.handlers:任務,與tasks不同的是只有在接受到通知時才會被觸發
5.templates:使用模板語言的文本文件
6.variables:變量,變量替換
3、playbook和臨時命令的比較
1.臨時命令不適合複雜配置管理或編配場景。
2.臨時命令一次只能調用一個模塊或一組參數。當需要多個操作時,必須使用多個臨時命令來執行。
3.playbook是描述要在受管理主機上實施的必要配置或程序性步驟的文件。playbook為配置管理和部署提供了強大而靈活的解決方案。playbook可以將冗長而複雜的管理任務變為可輕鬆重複的歷程,並且預測成果。
4、命令到playbook的演化
為了便於理解playbook,我們使用user模塊在指定節點docker-03上創建一個用戶名為newbie,uid為4000的用戶。
[root@docker-01 ~]# ansible -m user -a "name=newbie uid=4000 state=present" docker-03 docker-03 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "comment": "", "create_home": true, "group": 4000, "home": "/home/newbie", "name": "newbie", "shell": "/bin/bash", "state": "present", "system": false, "uid": 4000 }
如果寫成playbook
[root@docker-01 ~]# cat user.yml --- -name: Configure important user consistently hosts: docker-03 tasks: -name: newbie exists with UID 4000 user: name: newbie uid: 4000 state: present [root@docker-01 ~]# ansible-playbook user.yml PLAY [Configure important user consistently] *********************************** TASK [Gathering Facts] ********************************************************* ok: [docker-03] TASK [newbie exists with UID 4000] ********************************************* changed: [docker-03] PLAY RECAP ********************************************************************* docker-03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
paly的第一行以破折號和空格(指示play是列表的第一項)開始,然後是第一個key:name
name key描述paly的目的。name key是可選的,但推薦使用。
-name: Configure important user consistently
play中的第二個key是hosts屬性,指定運行play任務的主機。
hosts: docker-03
play中最後一個key是tasks屬性,為這個play運行的任務列表。
tasks: -name: newbie exists with UID 4000 user: name: newbie uid: 4000 state: present
注
playbook是YAML格式的文本文件,擴展名通常為yml。
playbook使用帶空格字符的縮進來表示數據結構。YAML對縮進使用了多少空格沒有嚴格的要求,但是有兩個基本規則:
1、層次機構中相同級別的數據元素(例如相同列表中的項)必須具有相同的縮進。
2、子項必須比其父項縮進的更多。
可以添加空行增加可讀性。
5、Tab鍵的使用
yml文件只能使用空格縮進,不能使用Tab,如果vim編輯器,可以通過編輯$HOME/.vimrc將Tab轉化為2個空格。文件如果不存在,則自己創建。
[root@docker-03 ~]# vim ~/.vimrc autocmd FileType yaml setlocal ai ts=2sw=2et
6、playbook的格式
playbook以三個破折號(—)作為文檔開始標記。以三個點(…)作為文檔結尾標記,儘管在實踐中經常被省略。
在這些標記之間,playbook由一組paly構成。YAML列表中的item以一個破折號開始,後跟空格。例如:
-name: Configure important user consistently -apple: This is an apple -orange: This is an orange
paly本身是key-value對的集合。同一個paly中keys應該有相同的縮進。下面的示例顯示了一個帶有三個keys的YAML代碼片段。前兩個keys的值很簡單。第三個key的列表中有三個items作為值。
name: Configure important user consistently hosts: docker-03 tasks: -first -second -third
tasks屬性列出要在主機上運行的任務,列表中的每個任務本身都是鍵值對的集合。
以下是另一個多tasks的演示
tasks: -name: web server is enabled service: name: httpd enabled: true -name: NTP server is enabled service: name: chronyd enabled: true -name: Postfix is enabled service: name: postfix enables: true
7、執行一個簡單的playbook
[root@docker-02 ~]# cat webserver.yml --- -name: play to setup web server hosts: docker-03 tasks: -name: latest httpd version installed yum: name: httpd state: latest [root@docker-02 ~]# ansible-playbook webserver.yml PLAY [play to setup web server] ************************************************ TASK [Gathering Facts] ********************************************************* ok: [docker-03] TASK [latest httpd version installed] ****************************************** changed: [docker-03] PLAY RECAP ********************************************************************* docker-03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
注
上面的輸出說明了為何有必要在playbook中將name屬性用於play和任務,即便此屬性是可選的。playbook執行時顯示name屬性的值。對於具有多個play和tasks的palybook,使用name屬性會給監控playbook的執行提供非常大的幫助。
一般來說,Ansible playbook中的任務是冪等(idempotent)的,可以安全的多次執行playbook。如果目標託管機已經處於正確的狀態,則不應進行任何修改。例如,假設前一個例子的劇本再次執行。
[root@docker-02 ~]# ansible-playbook webserver.yml PLAY [play to setup web server] ************************************************ TASK [Gathering Facts] ********************************************************* ok: [docker-03] TASK [latest httpd version installed] ****************************************** ok: [docker-03] PLAY RECAP ********************************************************************* docker-03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
注
所有任務狀態ok,且沒有發生任何change
8、語法驗證
在執行playbook前,最好進行驗證,確保其內容的語法正確無誤。ansible-playbook命令提供–syntax-check選項,可用於驗證playbook文件的語法。下例演示了一個playbook成功通過語法驗證。
[root@docker-02 ~]# ansible-playbook --syntax-check webserver.yml playbook: webserver.yml
語言驗證失敗時,將報語法錯誤。輸出中包含語法問題在playbook中的大致位置。下例演示了一個playbook語法驗證失敗,其中play的name屬性後缺少了空格分隔符。
[root@docker-02 ~]# ansible-playbook --syntax-check webserver.yml ERROR! Syntax Error whileloading YAML. mapping values are not allowed inthis context The error appears to be in'/root/webserver.yml': line 3, column 8, but may be elsewhere inthe file depending on the exact syntax problem. The offending line appears to be: -name: play to setup web server hosts: docker-03 ^ here
9、執行空運算
另一個有用的選項-C選項。這會使Ansible報告在執行該playbook時將會發生什麼更改,但不會對受管主機進行任何實際的更改。
下面演示了一個playbook的空運行,它在受管主機上安裝了最新版本的httpd軟件包。
[root@docker-02 ~]# ansible-playbook -C webserver.yml PLAY [play to setup web server] ************************************************ TASK [Gathering Facts] ********************************************************* ok: [docker-03] TASK [latest httpd version installed] ****************************************** changed: [docker-03] PLAY RECAP ********************************************************************* docker-03 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10、實戰2個plays,針對兩台主機分別操作
[root@docker-03 ~]# vim /etc/ansible/hosts [test1] 172.17.120.50 [test2] 172.17.120.51 [root@docker-03 ~]# vim test.yml --- #This is a simple playbook with two plays -name: first play hosts: 172.17.120.50 tasks: -name: first task yum: name: httpd state: present -name: second task service: name: httpd enabled: true -name: second play hosts: 172.17.120.51 tasks: -name: first task service: name: mariadb enabled: true [root@docker-03 ~]# ansible-playbook test.yml PLAY [first play] ****************************************************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************************************* ok: [172.17.120.50] TASK [first task] ****************************************************************************************************************************************************************************************** ok: [172.17.120.50] TASK [second task] ***************************************************************************************************************************************************************************************** changed: [172.17.120.50] PLAY [second play] ***************************************************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************************************* ok: [172.17.120.51] TASK [first task] ****************************************************************************************************************************************************************************************** changed: [172.17.120.51] PLAY RECAP ************************************************************************************************************************************************************************************************* 172.17.120.50 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 172.17.120.51 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

