課題: Ansibleにて一連の処理をノードごとに順次実行させたい
一連の処理を、あるノードにて実行、次に別のあるノードにて実行、さらに別のあるノードにて実行、といった順序で処理を行いたい。
通常のプログラミング言語ならば簡単だが、Ansibleでは、blockにループを適用できない為、回避する必要がある。
例えば以下はNG
- loop: "{{ play_hosts }}"
when: item == inventory_hostname
block:
- debug: msg="{{ inventory_hostname }} step 0"
- debug: msg="{{ inventory_hostname }} step 1"
ERROR! 'loop' is not a valid attribute for a Block にて失敗
方法1: play単位でserial: 1を使用
serialとは
Playbook例
---
- hosts: all
gather_facts: false
serial: 1
tasks:
- debug: msg="{{ inventory_hostname }} step 0"
- debug: msg="{{ inventory_hostname }} step 1"
実行例
$ ansible-playbook -i localhost0,localhost1 -c local site0.yml
PLAY [all] *************************************************************************************************************
TASK [debug] ***********************************************************************************************************
ok: [localhost0] => {
"msg": "localhost0 step 0"
}
TASK [debug] ***********************************************************************************************************
ok: [localhost0] => {
"msg": "localhost0 step 1"
}
PLAY [all] *************************************************************************************************************
TASK [debug] ***********************************************************************************************************
ok: [localhost1] => {
"msg": "localhost1 step 0"
}
TASK [debug] ***********************************************************************************************************
ok: [localhost1] => {
"msg": "localhost1 step 1"
}
PLAY RECAP *************************************************************************************************************
localhost0 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ここで、localhost0, localhost1 は、検証用に割り当てたlocalhostの別名
非常にシンプルではあるが、play単位なので小回りは効かない。
taskやblockに対しては、throttle: 1 が利用可能。(ansible2.9 から)
しかし、blockにthrottle: 1をつけた場合、block全体に対する制御ではなく、block内の個別のtaskに対する制御となり、行いたい処理とはならない。
方法2: loop:, when:, include_tasks: を組み合わせて使用
Playbook例
---
- hosts: all
gather_facts: false
tasks:
- loop: "{{ play_hosts }}"
when: item == inventory_hostname
include_tasks:
file: task01.yml
---
- debug: msg="{{ inventory_hostname }} step 0"
- debug: msg="{{ inventory_hostname }} step 1"
実行例
$ ansible-playbook -i localhost0,localhost1 -c local site1.yml
PLAY [all] *************************************************************************************************************
TASK [include_tasks] ***************************************************************************************************
skipping: [localhost0] => (item=localhost1)
skipping: [localhost1] => (item=localhost0)
included: /home/hiroyukionodera/repo/ansible-throttle-include_tasks/task01.yml for localhost0 => (item=localhost0)
included: /home/hiroyukionodera/repo/ansible-throttle-include_tasks/task01.yml for localhost1 => (item=localhost1)
TASK [debug] ***********************************************************************************************************
ok: [localhost0] => {
"msg": "localhost0 step 0"
}
TASK [debug] ***********************************************************************************************************
ok: [localhost0] => {
"msg": "localhost0 step 1"
}
TASK [debug] ***********************************************************************************************************
ok: [localhost1] => {
"msg": "localhost1 step 0"
}
TASK [debug] ***********************************************************************************************************
ok: [localhost1] => {
"msg": "localhost1 step 1"
}
PLAY RECAP *************************************************************************************************************
localhost0 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
意図通りの順序で実行されている。
なお、実際に使用する際には、バッティングのリスクを避ける為、loop変数をitemから変更しておくことをおすすめします。
参考:
- ワークアラウンド - gists · GitHub
https://gist.github.com/tbuchi888/ce5a6af9cdf9212e43bea5e3d3a0fa5d
コメント
ansible serialでGoogle検索を行うと、この様な状況に対応するための書き込みがいくつかありました。
Task単位の場合には、現在は、問題のあるdelegate_to + run_onceではなく、throttle: 1が使えるというのがAnsibleの進歩でしょうか。