Ansible playbook 編程詳解與各種小案例
主機規劃

添加用戶賬號
說明:
1、 運維人員使用的登錄賬號;
2、 所有的業務都放在 /app/ 下「yun用戶的家目錄」,避免業務資料亂放;
3、 該用戶也被 ansible 使用,因為幾乎所有的生產環境都是禁止 root 遠程登錄的(因此該 yun 用戶也進行了 sudo 提權),
1 # 使用一個專門的用戶,避免直接使用root用戶 2 # 添加用戶、指定家目錄并指定用戶密碼 3 # sudo提權 4 # 讓其它普通用戶可以進入該目錄查看資訊 5 useradd -u 1050 -d /app yun && echo '123456' | /usr/bin/passwd --stdin yun 6 echo "yun ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 7 chmod 755 /app/
Ansible 配置清單Inventory
之后文章都是如下主機配置清單
1 [yun@ansi-manager ansible_info]$ pwd 2 /app/ansible_info 3 [yun@ansi-manager ansible_info]$ cat hosts_key 4 # 方式1、主機 + 埠 + 密鑰 5 [manageservers] 6 172.16.1.180:22 7 8 [proxyservers] 9 172.16.1.18[1:2]:22 10 11 # 方式2:別名 + 主機 + 埠 + 密碼 12 [webservers] 13 web01 ansible_ssh_host=172.16.1.183 ansible_ssh_port=22 14 web02 ansible_ssh_host=172.16.1.184 ansible_ssh_port=22 15 web03 ansible_ssh_host=172.16.1.185 ansible_ssh_port=22
條件判斷-when
when 判斷在 ansible 任務中的使用頻率非常高,
例如判斷主機是否已經安裝指定的軟體包;對機器的作業系統進行判斷然后再根據不同的方法「yum或apt等」進行軟體包安裝;根據作業系統的版本判斷進行軟體包的安裝「是安裝MySQL還是Mariadb」等,
示例:根據主機名的不同,下載不同的檔案
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 4 5 -rw-rw-r-- 1 yun yun 950 Oct 26 10:22 test_when.yml 6 [yun@ansi-manager object04]$ cat test_when.yml 7 --- 8 # 根據 hostname 的不同下載不同的圖片 9 # 特殊組 all,對所有機器有效 10 - hosts: all 11 12 tasks: 13 - name: "download picture jvm-01-01.png" 14 get_url: 15 url: http://www.zhangblog.com/uploads/jvm/jvm-01-01.png 16 dest: /tmp/ 17 when: ansible_hostname == "ansi-haproxy01" 18 19 - name: "download picture jvm-01-02.png" 20 get_url: 21 url: http://www.zhangblog.com/uploads/jvm/jvm-01-02.png 22 dest: /tmp/ 23 when: ansible_hostname == "ansi-haproxy02" 24 25 - name: "other download picture jvm-01-03.png" 26 get_url: 27 url: http://www.zhangblog.com/uploads/jvm/jvm-01-03.png 28 dest: /tmp/ 29 # 從 facts 中獲取的變數,ansible_facts['ansible_hostname'] != "ansi-haproxy01" 錯誤寫法;ansible_hostname != "ansi-haproxy01" 正確寫法 30 #when: (ansible_hostname != "ansi-haproxy01") and (ansible_hostname != "ansi-haproxy02") # 寫法一 31 #或者如下3行 串列之間關系是 (and 與) 等同于上一行 32 #when: 33 # - ansible_hostname != "ansi-haproxy01" 34 # - ansible_hostname != "ansi-haproxy02" 35 #when: ansible_hostname is not match "ansi-haproxy0*" # 寫法二 36 when: (ansible_hostname is match "ansi-manager") or (ansible_hostname is match "ansi-web*") # 寫法三 37 38 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_when.yml # 語法檢測 39 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_when.yml # 預執行,測驗執行 40 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_when.yml # 執行 41 42 PLAY [all] ******************************************************************************************************* 43 44 TASK [Gathering Facts] ******************************************************************************************* 45 ok: [web01] 46 ok: [web02] 47 ok: [web03] 48 ok: [172.16.1.180] 49 ok: [172.16.1.181] 50 ok: [172.16.1.182] 51 52 TASK [download picture jvm-01-01.png] **************************************************************************** 53 skipping: [172.16.1.180] 54 skipping: [web01] 55 skipping: [web02] 56 skipping: [web03] 57 skipping: [172.16.1.182] 58 changed: [172.16.1.181] 59 60 TASK [download picture jvm-01-02.png] **************************************************************************** 61 skipping: [172.16.1.180] 62 skipping: [web01] 63 skipping: [web02] 64 skipping: [web03] 65 skipping: [172.16.1.181] 66 changed: [172.16.1.182] 67 68 TASK [other download picture jvm-01-03.png] ********************************************************************** 69 skipping: [172.16.1.181] 70 skipping: [172.16.1.182] 71 changed: [web02] 72 changed: [web01] 73 changed: [172.16.1.180] 74 changed: [web03] 75 76 PLAY RECAP ******************************************************************************************************* 77 172.16.1.180 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 78 172.16.1.181 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 79 172.16.1.182 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 80 web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 81 web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 82 web03 : ok=2 changed=1 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
標準回圈
注意:
1、回圈語法有兩種:loop 和 with_,
2、loop 是在ansible 2.5 添加的,with_ 是一直存在的,推薦使用 loop,在未來 with_ 可能被棄用,
簡單串列回圈
如果我們需要在 playbook 中啟動多個服務,或者下載多個檔案;按照之前所學的,那么我們需要寫多個 task,但這樣會使得 playbook 變得臃腫,因此這時我們就需要引進回圈了,
示例:一次啟動多個服務,下載多個檔案
使用 loop 方式【推薦】
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 20 5 -rw-rw-r-- 1 yun yun 594 Aug 23 22:10 test_loop.yml 6 [yun@ansi-manager object04]$ cat test_loop.yml 7 --- 8 # 啟動多個服務 和下載多個檔案 9 - hosts: proxyservers 10 11 tasks: 12 - name: "start httpd, rpcbind, network server" 13 service: 14 name: "{{ item }}" # 需要用引號引起來 15 state: started 16 loop: 17 - httpd 18 - rpcbind 19 - network 20 21 - name: "download multiple file" 22 get_url: 23 url: "{{ item }}" # 需要用引號引起來 24 dest: /tmp/ 25 loop: 26 - http://www.zhangblog.com/uploads/jvm/jvm-01-01.png 27 - http://www.zhangblog.com/uploads/jvm/jvm-01-02.png 28 - http://www.zhangblog.com/uploads/jvm/jvm-01-03.png 29 30 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_loop.yml # 語法檢測 31 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_loop.yml # 預執行,測驗執行 32 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_loop.yml # 執行
備注:以上方法可用在 yum 模塊中,
使用 with_items 方式
其中 playbook 檔案中僅把 loop 變為了 with_items,
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 20 5 -rw-rw-r-- 1 yun yun 594 Aug 23 22:10 test_with_items.yml 6 [yun@ansi-manager object04]$ cat test_with_items.yml 7 --- 8 # 啟動多個服務 和下載多個檔案 9 - hosts: proxyservers 10 11 tasks: 12 - name: "start httpd, rpcbind, network server" 13 service: 14 name: "{{ item }}" # 需要用引號引起來 15 state: started 16 with_items: 17 - httpd 18 - rpcbind 19 - network 20 21 - name: "download multiple file" 22 get_url: 23 url: "{{ item }}" # 需要用引號引起來 24 dest: /tmp/ 25 with_items: 26 - http://www.zhangblog.com/uploads/jvm/jvm-01-01.png 27 - http://www.zhangblog.com/uploads/jvm/jvm-01-02.png 28 - http://www.zhangblog.com/uploads/jvm/jvm-01-03.png 29 30 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_with_items.yml # 語法檢測 31 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_with_items.yml # 預執行,測驗執行 32 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_with_items.yml # 執行
如果用在 yum 模塊中則會報如下棄用告警,因此該方法不適用于 yum 模塊,

遍歷哈希串列
如果我們需要創建多個用戶并且每個用戶都有指定的附加組;或者要創建多個檔案,每個檔案屬主、屬組、權限不一樣;或者需要拷貝檔案,但是每個檔案的位置不一樣,且屬主、屬組、權限不一樣等等;那之前所學的簡單回圈就不能滿足我們的需求了,這時「哈希串列回圈」就閃亮登場了,
示例:
使用 loop 方式【推薦】
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 16 5 drwxrwxr-x 2 yun yun 56 Oct 26 16:03 file 6 -rw-rw-r-- 1 yun yun 1205 Oct 26 16:02 test_loop_hash.yml 7 [yun@ansi-manager object04]$ cat file/config_test.conf.j2 8 111 9 [yun@ansi-manager object04]$ cat file/yml_test_j2.yml 10 222 11 [yun@ansi-manager object04]$ cat test_loop_hash.yml 12 --- 13 # 使用回圈字典創建多個用戶,創建多個檔案,拷貝多個檔案 14 - hosts: proxyservers 15 16 tasks: 17 - name: "Create multiple user" 18 user: 19 name: "{{ item.user }}" 20 groups: "{{ item.groups }}" 21 loop: 22 - { user: "testuser1", groups: "root" } 23 - { user: "testuser2", groups: "root,yun" } 24 25 - name: "Create multiple file or dir" 26 file: 27 path: "{{ item.path }}" 28 owner: "{{ item.owner }}" 29 group: "{{ item.group }}" 30 mode: "{{ item.mode }}" 31 state: "{{ item.state }}" 32 loop: 33 - { path: "/tmp/with_items_testdir", owner: "yun", group: "root", mode: "755", state: "directory" } 34 - { path: "/tmp/with_items_testfile", owner: "bin", group: "bin", mode: "644", state: "touch" } 35 36 - name: "copy multiple file" 37 copy: 38 src: "{{ item.src }}" 39 dest: "{{ item.dest }}" 40 owner: "{{ item.owner }}" 41 group: "{{ item.group }}" 42 loop: 43 - { src: "./file/config_test.conf.j2", dest: "/tmp/with_items_testdir/", owner: "yun", group: "root" } 44 - { src: "./file/yml_test_j2.yml", dest: "/tmp/yml_test.yml", owner: "yun", group: "yun" } 45 46 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_loop_hash.yml # 語法檢測 47 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_loop_hash.yml # 預執行,測驗執行 48 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_loop_hash.yml # 執行
使用 with_items 方式
其中 playbook 檔案中僅把 loop 變為了 with_items,
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 16 5 drwxrwxr-x 2 yun yun 56 Oct 26 16:03 file 6 -rw-rw-r-- 1 yun yun 1205 Oct 26 16:02 test_with_items_hash.yml 7 [yun@ansi-manager object04]$ cat file/config_test.conf.j2 8 111 9 [yun@ansi-manager object04]$ cat file/yml_test_j2.yml 10 222 11 [yun@ansi-manager object04]$ cat test_with_items_hash.yml 12 --- 13 # 使用回圈字典創建多個用戶,創建多個檔案,拷貝多個檔案 14 - hosts: proxyservers 15 16 tasks: 17 - name: "Create multiple user" 18 user: 19 name: "{{ item.user }}" 20 groups: "{{ item.groups }}" 21 with_items: 22 - { user: "testuser1", groups: "root" } 23 - { user: "testuser2", groups: "root,yun" } 24 25 - name: "Create multiple file or dir" 26 file: 27 path: "{{ item.path }}" 28 owner: "{{ item.owner }}" 29 group: "{{ item.group }}" 30 mode: "{{ item.mode }}" 31 state: "{{ item.state }}" 32 with_items: 33 - { path: "/tmp/with_items_testdir", owner: "yun", group: "root", mode: "755", state: "directory" } 34 - { path: "/tmp/with_items_testfile", owner: "bin", group: "bin", mode: "644", state: "touch" } 35 36 - name: "copy multiple file" 37 copy: 38 src: "{{ item.src }}" 39 dest: "{{ item.dest }}" 40 owner: "{{ item.owner }}" 41 group: "{{ item.group }}" 42 with_items: 43 - { src: "./file/config_test.conf.j2", dest: "/tmp/with_items_testdir/", owner: "yun", group: "root" } 44 - { src: "./file/yml_test_j2.yml", dest: "/tmp/yml_test.yml", owner: "yun", group: "yun" } 45 46 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_with_items_hash.yml # 語法檢測 47 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_with_items_hash.yml # 預執行,測驗執行 48 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_with_items_hash.yml # 執行
遍歷字典
示例:
使用 loop 方式【推薦】
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 28 5 -rw-rw-r-- 1 yun yun 452 Oct 26 16:46 test_loop_dict.yml 6 [yun@ansi-manager object04]$ cat test_loop_dict.yml 7 --- 8 # 列印資訊 9 - hosts: manageservers 10 vars: 11 users: 12 alice: 13 name: Alice Appleworth 14 telephone: 123-456-7890 15 bob: 16 name: Bob Bananarama 17 telephone: 987-654-3210 18 19 tasks: 20 - name: "print user info" 21 debug: 22 msg: "User {{ item.key }}, userfullname: {{ item.value.name }} ({{ item.value.telephone }})" 23 # 將字典轉換為適合回圈的項表 第一種方式推薦 24 loop: "{{ users|dict2items }}" 25 #loop: "{{ lookup('dict', users) }}" 26 27 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_loop_dict.yml # 語法檢測 28 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_loop_dict.yml # 預執行,測驗執行 29 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_loop_dict.yml # 執行
使用 with_items 方式
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 28 5 -rw-rw-r-- 1 yun yun 458 Oct 26 16:47 test_with_items_dict.yml 6 [yun@ansi-manager object04]$ cat test_with_items_dict.yml 7 --- 8 # 列印資訊 9 - hosts: manageservers 10 vars: 11 users: 12 alice: 13 name: Alice Appleworth 14 telephone: 123-456-7890 15 bob: 16 name: Bob Bananarama 17 telephone: 987-654-3210 18 19 tasks: 20 - name: "print user info" 21 debug: 22 msg: "User {{ item.key }}, userfullname: {{ item.value.name }} ({{ item.value.telephone }})" 23 # with_dict 會直接決議字典 24 with_dict: "{{ users }}" 25 26 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_with_items_dict.yml # 語法檢測 27 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_with_items_dict.yml # 預執行,測驗執行 28 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_with_items_dict.yml # 執行
變數回圈-vars
針對yum 安裝多個包很有用,其他則會報出警告,
1 [yun@ansi-manager object04]$ pwd 2 /app/ansible_info/object04 3 [yun@ansi-manager object04]$ ll 4 total 36 5 -rw-rw-r-- 1 yun yun 252 Oct 26 17:46 test_cycle_vars.yml 6 [yun@ansi-manager object04]$ cat test_cycle_vars.yml 7 --- 8 # 批量包安裝 9 - hosts: proxyservers 10 11 tasks: 12 - name: "Install multiple packages" 13 yum: 14 name: "{{ multi_package }}" 15 state: present 16 vars: 17 multi_package: 18 - tree 19 - nc 20 - tcpdump 21 22 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key --syntax-check test_cycle_vars.yml # 語法檢測 23 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key -C test_cycle_vars.yml # 預執行,測驗執行 24 [yun@ansi-manager object04]$ ansible-playbook -b -i ../hosts_key test_cycle_vars.yml # 執行
該方法不一定適用于其他模塊

觸發器-handlers
當我們修改了服務的組態檔時,這時我們需要去重啟服務,那么 handlers 就可以派上用場了,
注意事項:
1、無論多少個 task 通知了相同的 handlers,handlers 僅會在所有 tasks 結束后運行一次,
2、只有 task 發生改變了才會通知 handlers,沒有改變則不會通知和觸發 handlers,
3、不能用 handlers 替代 task ,
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 24 5 drwxrwxr-x 2 yun yun 129 Aug 24 11:41 file 6 -rw-rw-r-- 1 yun yun 1029 Aug 24 11:57 test_handlers.yml 7 [yun@ansi-manager object05]$ ll file/ # 涉及組態檔 8 total 20 9 -rw-r--r-- 1 yun yun 11767 Aug 24 11:41 httpd.conf.j2 10 [yun@ansi-manager object05]$ vim file/httpd.conf.j2 # 組態檔修改的地方 11 ………… 12 # Change this to Listen on specific IP addresses as shown below to 13 # prevent Apache from glomming onto all bound IP addresses. 14 # 15 #Listen 12.34.56.78:80 16 ###### 埠改為變數 17 Listen {{ httpd_port }} 18 19 ………… 20 [yun@ansi-manager object05]$ cat test_handlers.yml # yml 檔案 21 --- 22 # 比如安裝配置啟動 httpd,當我們修改組態檔,重啟 httpd 服務 23 # 要求:修改配置,重啟一個或多個服務 24 - hosts: proxyservers 25 # 這里為了演示方便,因此變數直接就寫在了該檔案中 26 vars: 27 - httpd_port: 8081 28 29 tasks: 30 - name: "Install httpd" 31 yum: 32 name: "{{ packages }}" 33 state: present 34 vars: 35 packages: 36 - httpd 37 - httpd-tools 38 39 - name: "Httpd config" 40 template: 41 src: ./file/httpd.conf.j2 42 dest: /etc/httpd/conf/httpd.conf 43 # 一個通知 44 # notify: "Restart httpd server" 45 # 多個通知 46 notify: 47 - "Restart httpd server" 48 - "Restart crond server" 49 50 - name: "Start httpd server" 51 systemd: 52 name: httpd 53 state: started 54 enabled: yes 55 56 handlers: 57 - name: "Restart httpd server" 58 systemd: 59 name: httpd 60 state: restarted 61 62 - name: "Restart crond server" 63 systemd: 64 name: crond 65 state: restarted 66 67 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_handlers.yml # 語法檢測 68 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_handlers.yml # 預執行,測驗執行 69 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_handlers.yml # 執行
任務標簽-tags
默認情況下,當我們執行一個 playbook 時,會執行該 playbook 中所有的任務,如果只想執行一個 task 或者部分 task 用于除錯或者需求就是執行部分 task,那么可以使用 ansible 的標簽(tags)功能給單獨 task 或者全部 task 打上標簽,之后利用這些標簽來指定要運行哪些 playbook 任務,或不運行哪些 playbook 任務,
打標簽方式
對一個 task 打一個標簽;
對一個 task 打多個標簽;
對多個 task 打一個標簽
標簽如何運用
-t TAGS, --tags=TAGS:執行指定的 tag 標簽任務;多個標簽使用逗號分開
--skip-tags=SKIP_TAGS:跳過指定標簽不執行,執行指定外的 task「標簽作用于 task 上,即使該task還有其他標簽,這個 task 也不會被執行」;多個標簽使用逗號分開
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 8 5 drwxrwxr-x 2 yun yun 27 Oct 26 18:07 file 6 -rw-rw-r-- 1 yun yun 1004 Oct 26 19:21 test_tags.yml 7 [yun@ansi-manager object05]$ cat test_tags.yml 8 --- 9 # tags 標簽測驗 10 - hosts: proxyservers 11 # 這里為了演示方便,因此變數直接就寫在了該檔案中 12 vars: 13 - httpd_port: 8081 14 15 tasks: 16 - name: "Install httpd" 17 yum: 18 name: "{{ packages }}" 19 state: present 20 vars: 21 packages: 22 - httpd 23 - httpd-tools 24 tags: 25 - httpd_server 26 - httpd_install 27 28 - name: "Httpd config" 29 template: 30 src: ./file/httpd.conf.j2 31 dest: /etc/httpd/conf/httpd.conf 32 notify: "Restart httpd server" 33 tags: 34 - httpd_server 35 - httpd_config 36 37 - name: "Start httpd server" 38 systemd: 39 name: httpd 40 state: started 41 enabled: yes 42 tags: 43 - httpd_server 44 - httpd_start 45 46 - name: "Create dir" 47 file: 48 path: /tmp/with_items_testdir 49 state: directory 50 tags: create_dir 51 52 handlers: 53 - name: "Restart httpd server" 54 systemd: 55 name: httpd 56 state: restarted
playbook 標簽查看
1 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_tags.yml # 語法檢測 2 ## 查看 playbook 中的任務和標簽 3 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml --list-tasks 4 5 playbook: test_tags.yml 6 7 play #1 (proxyservers): proxyservers TAGS: [] 8 tasks: 9 Install httpd TAGS: [httpd_install, httpd_server] 10 Httpd config TAGS: [httpd_config, httpd_server] 11 Start httpd server TAGS: [httpd_server, httpd_start] 12 Create dir TAGS: [create_dir] 13 ## 查看 playbook 中的標簽 14 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml --list-tags 15 16 playbook: test_tags.yml 17 18 play #1 (proxyservers): proxyservers TAGS: [] 19 TASK TAGS: [create_dir, httpd_config, httpd_install, httpd_server, httpd_start]
playbook 執行
1 ## 單個標簽執行 2 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml -t httpd_install 3 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml -t httpd_server 4 ## 多個標簽執行 5 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml -t httpd_install,httpd_config,httpd_start 6 ## 跳過哪些標簽不執行「標簽作用于 task 上,即使該 task 還有其他標簽,這個 task 也不會被執行」 7 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml --skip-tags httpd_server 8 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml --skip-tags httpd_install,create_dir 9 ## 執行整個 playbook 10 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_tags.yml
檔案參考/復用-include與import
在實際應用中,是不可能將所有 task 寫在一個 playbook 中的,需要進行拆分,方便后期重復使用,這樣后面寫其他 playbook 的時候,如果有重復的,那么直接參考之前寫的即可,
Includes 與 Imports
1、include 和 import 雖然功能相近,但是 ansible 執行引擎對他們的處理卻截然不同,
2、所有 import* 陳述句都會在決議 playbook 時進行預處理,「提前準備好工具」
3、所有 include* 陳述句都是在執行 playbook 時遇到再處理,「需要什么工具,再拿什么工具」
PS:include 模塊:這個模塊還將支持一段時間,但在不久的將來可能會棄用「最好不要使用這個模塊」,
示例
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 32 5 drwxrwxr-x 2 yun yun 103 Aug 24 19:51 file_yml 6 -rw-rw-r-- 1 yun yun 518 Aug 24 19:56 test_include.yml 7 [yun@ansi-manager object05]$ ll file_yml/ 8 total 16 9 -rw-rw-r-- 1 yun yun 136 Aug 24 19:51 httpd_config.yml 10 -rw-rw-r-- 1 yun yun 133 Aug 24 19:41 httpd_install.yml 11 -rw-rw-r-- 1 yun yun 80 Aug 24 19:42 httpd_restart.yml 12 -rw-rw-r-- 1 yun yun 93 Aug 24 19:41 httpd_start.yml 13 ## 每個小 yml 檔案的具體內容 14 [yun@ansi-manager object05]$ cat file_yml/httpd_install.yml 15 - name: "Install httpd" 16 yum: 17 name: "{{ packages }}" 18 state: present 19 vars: 20 packages: 21 - httpd 22 - httpd-tools 23 24 [yun@ansi-manager object05]$ cat file_yml/httpd_config.yml 25 - name: "Httpd config" 26 template: 27 src: ./file/httpd.conf.j2 28 dest: /etc/httpd/conf/httpd.conf 29 notify: "Restart httpd server" 30 31 [yun@ansi-manager object05]$ cat file_yml/httpd_start.yml 32 - name: "Start httpd server" 33 systemd: 34 name: httpd 35 state: started 36 enabled: yes 37 38 [yun@ansi-manager object05]$ cat file_yml/httpd_restart.yml 39 - name: "Restart httpd server" 40 systemd: 41 name: httpd 42 state: restarted 43 44 ###### 主呼叫 yml 檔案內容 ###### 45 [yun@ansi-manager object05]$ cat test_include.yml 46 --- 47 # 呼叫其他 yml 檔案 48 - hosts: proxyservers 49 # 這里為了演示方便,因此變數直接就寫在了該檔案中 50 vars: 51 - httpd_port: 8083 52 53 tasks: 54 - include_tasks: ./file_yml/httpd_install.yml 55 - include_tasks: ./file_yml/httpd_config.yml 56 - include_tasks: ./file_yml/httpd_start.yml 57 58 handlers: 59 # 使用 import 進行預處理,這樣防止 notify 時,在 handlers 找不到對應的資訊 60 - import_tasks: ./file_yml/httpd_restart.yml 61 62 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_include.yml # 語法檢測 63 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_include.yml # 預執行,測驗執行 64 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_include.yml # 執行
忽略錯誤-ignore_errors
在 playbook 執行程序中,默認情況下如果有錯誤發生,那么后面的 task 就不執行,并且退出當前的 playbook,
如果我們對某些 task 執行結果不關心,不管執行是否成功,后面的 task 也要繼續執行,那就需要通過 ignore_errors 來忽略當前 task 的錯誤結果,讓后面的 task 繼續往下執行,
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 36 5 -rw-rw-r-- 1 yun yun 479 Aug 26 09:24 test_ignore_errors.yml 6 [yun@ansi-manager object05]$ cat test_ignore_errors.yml 7 --- 8 # ignore_errors 測驗 9 - hosts: proxyservers 10 11 tasks: 12 - name: "Install httpd" 13 yum: 14 name: "{{ packages }}" 15 state: present 16 vars: 17 packages: 18 - httpd 19 - httpd-tools 20 21 - name: "Shell false" 22 shell: /bin/false 23 # 是否忽略該 task 的錯誤 「打開或關閉注釋,對比」 24 ignore_errors: True 25 26 - name: "Create dir" 27 file: 28 path: /tmp/with_items_testdir 29 state: directory 30 31 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_ignore_errors.yml # 語法檢測 32 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_ignore_errors.yml # 預執行,測驗執行 33 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_ignore_errors.yml # 執行
默認情況

使用了 ignore_errors 的情況

自定義錯誤判定條件-failed_when
命令不依賴回傳狀態碼來判定是否執行失敗,而是要查看命令回傳內容來決定,比如回傳內容中包括 command not found 字串,則判定為失敗,
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 48 5 -rw-rw-r-- 1 yun yun 369 Aug 29 16:12 test_custom_error.yml 6 [yun@ansi-manager object05]$ cat test_custom_error.yml 7 --- 8 # 自定義錯誤條件 9 - hosts: proxyservers 10 11 tasks: 12 - name: "this command prints 'command not found' if not find" 13 shell: "kkk -x" # 測驗一 14 #shell: "/bin/kkk -x" # 測驗二 15 register: shell_result 16 failed_when: "'command not found' in shell_result['stderr']" 17 18 - name: "print shell_result info" 19 debug: 20 msg: "{{ shell_result['stderr'] }}" 21 22 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_custom_error.yml # 語法檢測 23 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_custom_error.yml # 預執行,測驗執行 24 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_custom_error.yml # 執行
強制呼叫觸發器-force_handlers
通常情況下,當 task 執行失敗后,playbook 會終止,任何在此之前已經被 task notify 的 handlers 都不會被執行,
此時,如果你在 playbook 中設定了 force_handlers: yes 引數,則被通知的 handlers 就會被強制執行(有些特殊場景可能會使用到),
如示例,在一個 playbook 中,如果組態檔的 task 已經被執行成功,并且 notify 了 handlers,之后必須重啟服務,那么我們會強制要求:即使后續的 task 執行失敗,之前被通知的 handlers 也必須執行,
如果不強制執行就變成了,第一次執行時:組態檔修改成功,但由于之后有 task 執行失敗,導致 playbook 終止,后續 handlers 沒有被呼叫,對應服務沒有重啟;第二次執行時:組態檔沒發生改變「因此第一次已經更新了組態檔」,因此不會通知 handlers,最終結果就是配置改變了,但是就是沒有重啟服務,顯然不符合我們的初衷,
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 40 5 drwxrwxr-x 2 yun yun 129 Aug 24 14:28 file 6 -rw-rw-r-- 1 yun yun 909 Aug 29 12:23 test_error_deal.yml 7 [yun@ansi-manager object05]$ cat test_error_deal.yml 8 --- 9 # 即使 task 執行錯誤,之前已 notify 的 handlers 必須被執行 10 - hosts: proxyservers 11 # 這里為了演示方便,因此變數直接就寫在了該檔案中 12 vars: 13 - httpd_port: 8087 14 # 即使 task 執行錯誤,之前已 notify 的 handlers 必須被執行 15 force_handlers: yes 16 17 tasks: 18 - name: "Install httpd" 19 yum: 20 name: "{{ packages }}" 21 state: present 22 vars: 23 packages: 24 - httpd 25 - httpd-tools 26 27 - name: "Httpd config" 28 template: 29 src: ./file/httpd.conf.j2 30 dest: /etc/httpd/conf/httpd.conf 31 notify: "Restart httpd server" 32 33 - name: "Start httpd server" 34 systemd: 35 name: httpd 36 state: started 37 enabled: yes 38 39 # /bin/false 回傳狀態碼為1,不為0 40 - name: "Shell task" 41 shell: /bin/false 42 43 - name: "Create dir" 44 file: 45 path: /tmp/with_items_testdir 46 state: directory 47 48 handlers: 49 - name: "Restart httpd server" 50 systemd: 51 name: httpd 52 state: restarted 53 54 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_error_deal.yml # 語法檢測 55 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_error_deal.yml # 預執行,測驗執行 56 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_error_deal.yml # 執行
抑制changed狀態-changed_when
ansible 會自動判斷模塊執行狀態,command、shell 及其它模塊如果修改了遠程主機狀態則被判定為 changed 狀態,不過也可以自己決定達到 changed 狀態的條件,
當我們在 playbook 中使用 shell 或者 command 模塊時,每次 task 執行狀態都是 changed,原因是因為每次我們都去執行獲取當前資料,而不是一個固化的狀態,
但在實際應用中,我們可能不需要 shell 或者 command 模塊執行后的 changed 狀態,這時我們就需要通過 changed_when: false 來抑制這個改變,
當然上述的 changed_when: false 可以在任何模塊中使用,不局限于 shell 和 command 模塊,只是我們常用于這兩個模塊而已,
1 [yun@ansi-manager object05]$ pwd 2 /app/ansible_info/object05 3 [yun@ansi-manager object05]$ ll 4 total 44 5 -rw-rw-r-- 1 yun yun 299 Aug 29 14:47 test_changed_when.yml 6 [yun@ansi-manager object05]$ cat test_changed_when.yml 7 --- 8 # 使用 changed_when: false 抑制 changed 狀態 9 - hosts: proxyservers 10 11 tasks: 12 - name: "Shell task" 13 shell: netstat -lntp | grep 'httpd' 14 register: check_httpd 15 # changed_when: false # 任何時候,都不為 changed 狀態 16 #### check_httpd['stdout'] 不包含 httpd 為 true,否則 false 17 changed_when: "'httpd' not in check_httpd['stdout']" # 結果為 false 18 19 - name: "Debug output" 20 debug: 21 msg: "{{ check_httpd.stdout }}" 22 23 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key --syntax-check test_changed_when.yml # 語法檢測 24 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key -C test_changed_when.yml # 預執行,測驗執行 25 [yun@ansi-manager object05]$ ansible-playbook -b -i ../hosts_key test_changed_when.yml # 執行
完畢!
———END———
如果覺得不錯就關注下唄 (-^O^-) !

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/95021.html
標籤:Linux
上一篇:引導 ARM Linux
下一篇:作業系統-生磁盤的使用
