ansible基礎-task控制


1. 前言

很多情況下,一個play是否執行會依賴於某個(些)變量的值,這個變量可以來自自定義變量、facts,甚至是另一個task的執行結果。

ansible通過變量判定task是否執行,我們稱之為task控制。

在我看來,ansible的控制語句帶來的最大的好處就是使部署代碼更加健壯,舉幾個例子:

  • 利用「ansible_os_family」變量使部署代碼支持更多版本的操作系統
  • 避免很多冗余無用的代碼執行,提高代碼執行效率
  • 避免很多task意外的執行失敗
  • 使playbook滿足冪等性

2. when語句

ansible使用最頻繁的task控制語句就是「when」語句。

when語句可以在task中直接使用,也可以與include*、import*、roles、vars_files、incloud_vars等引入語句搭配使用。執行結果也比較通俗易懂,前者用來判斷task是否執行,后者用來判斷task是否引用。

when語句引用變量時不用加「{{}}」。在when語句中,ansible將不帶引號的字符串認定為變量,所以如果使用字符串記得加單(雙)引號。

對不同數據類型的判斷可以使用不同的條件語句:

使用「==」:

tasks: - name: "shut down Debian flavored systems" command: /sbin/shutdown -t now when: ansible_facts['os_family'] == "Debian"

使用「is」:

tasks: - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined - fail: msg="Bailing out. this play requires 'bar'" when: bar is undefined - command: /bin/something when: result is failed # In older versions of ansible use ``success``, now both are valid but succeeded uses the correct tense. - command: /bin/something_else when: result is succeeded - command: /bin/still/something_else when: result is skipped

使用「in」:

when: "'reticulating splines' in output"

使用運算符(記得使用「int」將參數轉為整數類型):

tasks: - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_facts['lsb']['major_release']|int >= 6

直接判斷變量的True/False:

tasks: - shell: echo "This certainly is epic!" when: epic - shell: echo "This certainly isn't epic!" when: not epic

多個條件判斷語句結合:

tasks: - name: "shut down CentOS 6 and Debian 7 systems" command: /sbin/shutdown -t now when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")

when語句的參數也支持列表,等價於「and」:

tasks: - name: "shut down CentOS 6 systems" command: /sbin/shutdown -t now when: - ansible_facts['distribution'] == "CentOS"
      - ansible_facts['distribution_major_version'] == "6"

3 與引用相關的控制語句

3.1 條件導入play

上面說到when語句可以控制task是否被引用,例如當變量「output」包含字符串「reticulating splines」時再導入playbook「sometasks.yml」:

- import_tasks: tasks/sometasks.yml when: "'reticulating splines' in output"

其他的導入語句import_playbook;include_tasks;import_role;include_role;roles等語句使用方法也類似上面的示例。

3.2 條件導入變量文件

同樣,當task中使用「include_vars」語句導入變量文件時,也可以控制其導入,格式與導入play類似,這里就不舉例了。

4 與register相關的控制語句

比較特殊的,我們可以基於一個task的執行結果來判斷某個task是否執行,此時就用到了「register」語句。這里列舉一個我在部署openshift時的例子:

遇到的問題:

部署harbor時,我想用「docker network connect」命令將harbor_harbor和ldapserver這兩個容器網絡打通,但是發現如果這兩個容器是已經關聯的狀態,再次執行playbook時拋報錯「Error response from daemon: service endpoint with name ldapserver already exists」這樣就不滿足ansible的冪等性。

解決辦法

第一個task是查詢harbor_harbor的網絡連接信息,並將其注冊為一個變量「harbor_conn_info」:

- name: Get network harbor_harbor connection information shell: >
    /usr/bin/docker network inspect harbor_harbor register: harbor_conn_info

上面示例中,變量「harbor_conn_info」是「/usr/bin/docker network inspect harbor_harbor」命令的執行結果,ansible從執行結果中查找「ldapserver」字符串,如果未查到(即find函數結果返回值為-1)則執行「docker network connect」命令。

通過這個例子,說明ansible的控制語句能夠使部署代碼滿足最基本冪等性要求,也能使代碼更加健壯

5 基於變量的控制語句

基於變量的控制語句是另外一種task控制方式,不需要「when」語句,例如:

---
- hosts: all remote_user: root vars_files: - "vars/common.yml"
    - [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/os_defaults.yml" ] tasks: - name: make sure apache is started service: name={{ apache }} state=started

6 本節應該掌握的技能

  • 掌握task控制的作用以及帶來的好處
  • 會在 playbook中使用when語句
  • 掌握register+when的配合使用

7 參考鏈接

  • https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html

 

歡迎大家關注我的公眾號:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM