英文:
ansible serial do not continue when one host failed
问题
我正在使用 ansible [core 2.11.4] 在 RH 8.7 上
我意识到当我以串行模式运行 ansible(在多台主机上运行一些任务)并且某个主机上的任务失败时,整个 ansible 就会中断。
这是一个 bug 吗?
在非串行模式下,它会继续在下一个主机上运行。
英文:
I am using ansible [core 2.11.4] on RH 8.7
I realized that when I run ansible in serial mode ( to run some tasks on multiple hosts ) and task is failed on one host, then ansible breaks at all.
Is it a bug or ?
In non-serial mode it continue play on next hosts.
答案1
得分: 3
确切发生的是,如果在串行批处理中所有主机都失败,那么所有剩余主机的整个执行都会停止。如果该批次中有单个主机仍然成功,则会继续执行下一个主机。通过在 play 上设置 max_fail_percentage
选项 可以调整该行为,以便在有太多失败主机时仍然失败。
以下是一个虚拟示例,仅用于演示默认情况下,如果串行批处理中至少有一个主机成功,则会播放所有主机。正如你将看到的,我使用了 4 个虚假主机,并故意失败了偶数主机。
- 使用批处理大小为 50%(即每批 2 个主机)时,它会通过所有主机到最后(每批中 1 个主机失败超过 2 个)。
- 如果将批处理大小降低到 25%(即每批 1 个主机),你会看到它在遇到第一个失败的偶数主机后停止(即当前批次中的所有主机都失败)。
给定 fake_inventory.yml
:
---
all:
vars:
ansible_connection: local
hosts:
"host[1:4]":
playbook.yml
---
- hosts: all
gather_facts: false
serial: "{{ batch_size }}"
tasks:
- name: Doesn't fail
command: ls
- name: Fails for even hosts
vars:
is_even: "{{ inventory_hostname | regex_replace('host(\\d)', '\') | int % 2 == 0 }}"
fail:
msg: "I'm an even host, failing"
when: is_even
- name: Doesn't fail but played only on odd hosts since we failed even
command: /bin/true
输出(使用不同批处理大小进行两次运行)
$ ansible-playbook -i fake_inventory.yml -e batch_size=50% playbook.yml
PLAY [all] ***************************************************************************************************************************************
TASK [Doesn't fail] ******************************************************************************************************************************
changed: [host2]
changed: [host1]
TASK [Fails for even hosts] **********************************************************************************************************************
skipping: [host1]
fatal: [host2]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
TASK [Doesn't fail but played only on odd hosts since we failed even] ****************************************************************************
changed: [host1]
PLAY [all] ***************************************************************************************************************************************
TASK [Doesn't fail] ******************************************************************************************************************************
changed: [host3]
changed: [host4]
TASK [Fails for even hosts] **********************************************************************************************************************
skipping: [host3]
fatal: [host4]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
TASK [Doesn't fail but played only on odd hosts since we failed even] ****************************************************************************
changed: [host3]
PLAY RECAP ***************************************************************************************************************************************
host1 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host2 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
host3 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host4 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
$ ansible-playbook -i fake_inventory.yml -e batch_size=25% playbook.yml
PLAY [all] ***************************************************************************************************************************************
TASK [Doesn't fail] ******************************************************************************************************************************
changed: [host1]
TASK [Fails for even hosts] **********************************************************************************************************************
skipping: [host1]
TASK [Doesn't fail but played only on odd hosts since we failed even] ****************************************************************************
changed: [host1]
PLAY [all] ***************************************************************************************************************************************
TASK [Doesn't fail] ******************************************************************************************************************************
changed: [host2]
TASK [Fails for even hosts] **********************************************************************************************************************
fatal: [host2]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
PLAY RECAP ***************************************************************************************************************************************
host1 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host2 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
英文:
What happens exactly is if all hosts fail in the serial batch then the entire play is stopped for all remaining hosts. If a single host in that batch still succeeds then it goes on to the next hosts. That behavior can be adapted by setting the max_fail_percentage
option on the play to still fail if there are two many failed hosts.
The following is a dummy example just to show that by default all hosts are played if at least one succeeds in the serial batch. As you will see, I used 4 fake hosts and voluntarily failed even hosts.
- When using a batch size of 50% (which makes 2 hosts per batch) it goes through all hosts to the end (1 host fails over 2 in batch).
- If you lower the batch size to 25% (i.e. 1 host per batch) you will see it stops after the first encountered even failed host (i.e. all host in current batch failed).
Given the fake_inventory.yml
:
---
all:
vars:
ansible_connection: local
hosts:
"host[1:4]":
The playbook.yml
---
- hosts: all
gather_facts: false
serial: "{{ batch_size }}"
tasks:
- name: Doesn't fail
command: ls
- name: Fails for even hosts
vars:
is_even: "{{ inventory_hostname | regex_replace('host(\\d)', '\') | int % 2 == 0 }}"
fail:
msg: "I'm an even host, failing"
when: is_even
- name: Doesn't fail but played only on odd hosts since we failed even
command: /bin/true
Gives (2 runs with different batch size)
$ ansible-playbook -i fake_inventory.yml -e batch_size=50% playbook.yml
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Doesn't fail] ***********************************************************************************************************************************************************************************************
changed: [host2]
changed: [host1]
TASK [Fails for even hosts] ***************************************************************************************************************************************************************************************
skipping: [host1]
fatal: [host2]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
TASK [Doesn't fail but played only on odd hosts since we failed even] *********************************************************************************************************************************************
changed: [host1]
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Doesn't fail] ***********************************************************************************************************************************************************************************************
changed: [host3]
changed: [host4]
TASK [Fails for even hosts] ***************************************************************************************************************************************************************************************
skipping: [host3]
fatal: [host4]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
TASK [Doesn't fail but played only on odd hosts since we failed even] *********************************************************************************************************************************************
changed: [host3]
PLAY RECAP ********************************************************************************************************************************************************************************************************
host1 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host2 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
host3 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host4 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
$ ansible-playbook -i fake_inventory.yml -e batch_size=25% playbook.yml
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Doesn't fail] ***********************************************************************************************************************************************************************************************
changed: [host1]
TASK [Fails for even hosts] ***************************************************************************************************************************************************************************************
skipping: [host1]
TASK [Doesn't fail but played only on odd hosts since we failed even] *********************************************************************************************************************************************
changed: [host1]
PLAY [all] ********************************************************************************************************************************************************************************************************
TASK [Doesn't fail] ***********************************************************************************************************************************************************************************************
changed: [host2]
TASK [Fails for even hosts] ***************************************************************************************************************************************************************************************
fatal: [host2]: FAILED! => {"changed": false, "msg": "I'm an even host, failing"}
PLAY RECAP ********************************************************************************************************************************************************************************************************
host1 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
host2 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
答案2
得分: 1
根据文档:
默认情况下,Ansible 并行运行,针对 hosts: 字段中设置的模式中的所有主机执行。如果您想一次只管理少数主机,例如在滚动更新期间,您可以使用 serial 关键字来定义 Ansible 应一次管理多少主机。
在您的 playbook 上添加 serial: x
参数允许在同一时间在 x 个主机上执行任务。
例如,如果您定义 serial: 1
,任务将逐个主机执行:如果一个主机失败,执行将停止。
英文:
I think you're misunderstanding the purpose of the serial parameter.
According to the documentation :
> By default, Ansible runs in parallel against all the hosts in the pattern you set in the hosts: field of each play. If you want to manage only a few machines at a time, for example during a rolling update, you can define how many hosts Ansible should manage at a single time using the serial keyword
Adding the serial: x
parameter on your playbook allow playing the task on x
host in the same time.
For example, if you define serial: 1
, the task is gonna be played on each host 1 by 1 : if one host failed, the play stop.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论