ansible串行执行,当一个主机失败时不继续。

huangapple go评论65阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年3月9日 23:38:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686837.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定