Ansible run_once+when觸發的BUG及其處理方式


關於run_once和when:
when

Conditional expression, determines if an iteration of a task is run or not.

run_once

Boolean that will bypass the host loop, forcing the task to attempt to execute on the first host available and afterwards apply any results and facts to all active hosts in the same batch.

when表示只在符合when條件的host上執行task,run_once表示只在當前host group中第一個可用host上執行task。

有時候我們需要兩者混用以便實現:在符合when條件的首個host上執行task的功能。

如果用一個自創的關鍵字來描述上述功能,那么比較符合的應該是:run_once_when_condition_true.

但當when和run_once同時出現時,實際表現是:無論在第一個host上when條件是否滿足,都不會繼續在其他host執行了,如果第一個host上when條件為false那么task會被直接skipped。

關於這個BUG在ansible的github issues中有一個帖子:

run_once: true with delegate_to now getting skipped (2.3.0) · Issue #23594 · ansible/ansible (github.com)

issue中作者試圖使用delegate_to來解決此問題,但實際上這種方式並不靠譜。

Ansible可能會在未來推出類似於run_once_when_condition_true的功能,但現在並沒有(截止2021年2月)。

 

變通的方式:

run_once和when同時出現會導致以下BUG:如果第一個host滿足when條件那么BUG不觸發,否則task被跳過(就是因為在第一個host上when條件未滿足)。

一個可行的辦法是將兩者分開,那么就需要使用include關鍵字。

核心邏輯是:

1.先使用when條件過濾出所有滿足條件的host。

2.再在include子任務中使用run_once執行任務。

示例:

driver.yml

- include_tasks: tasks_to_include.yml
  when: conditional_matching_multiple_hosts

tasks_to_include.yml

- debug: msg="only run on one of the matching hosts"
  run_once: true
driver.yml負責過濾出符合條件的hosts,子任務通過run_once實現只在單個host執行的功能,變相的實現了run_once_when_condition_true的目的。
 
注意事項:
Ansible2.4以后使用include_tasks替代了之前的include,我在ansible2.9的環境下使用include發現會跳過when條件的篩選直接執行子任務,換為include_tasks才正常。

最后:

本文中描述的方法是在playbook的hosts配置文件不可變的前提前提出的,如果能在hosts文件生成階段就加一個run_sth=true/false的配置,那么只需要使用簡單的when條件判斷就可以了。


免責聲明!

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



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