Ansible 使用多个主机中止进一步的任务执行

Ansible 使用多个主机中止进一步的任务执行,ansible,Ansible,使用Ansible v2.9.12 问题:当一个任务失败时,当多个主机执行该任务时,我想尝试失败/停止播放。从这个意义上说,Ansible应该中止进一步执行的任务。配置应在角色中工作,因此不可能使用串行,也不可能使用不同的重头戏 榜样 - hosts: - host1 - host2 - host3 any_errors_fatal: true tasks: - name: always fail shell: /bin/false

使用Ansible v2.9.12

问题:当一个任务失败时,当多个主机执行该任务时,我想尝试失败/停止播放。从这个意义上说,Ansible应该中止进一步执行的任务。配置应在角色中工作,因此不可能使用
串行
,也不可能使用不同的重头戏

榜样

- hosts:
    - host1
    - host2
    - host3
  any_errors_fatal: true
  tasks:
    - name: always fail
      shell: /bin/false
      throttle: 1
提供

===== task | always fail =======
host1: fail
host2: fail
host3: fail
也就是说,任务仍然在第二台主机和第三台主机上执行。一旦主机上的任务失败,我希望整个游戏都失败/停止。当任务在最后一台主机上失败时,Ansible也应该中止

预期结果

===== task | always fail =======
host1: fail
host2: not executed/skipped, cause host1 failed
host3: not executed/skipped, cause host1 failed
正如你所看到的,我已经摆弄过了,但没有成功


背景信息:我一直在为mysql开发一个幂等Ansible角色。可以使用多台主机设置群集。该角色还支持添加

仲裁者没有安装mysql应用程序,但在游戏中仍然需要主机

现在,想象三位主持人。Host1是仲裁器,host2和host3安装了mysql,安装在集群中。应用程序由Ansible角色设置。 现在,Ansible在第二/第三/第四/任何时间执行该角色,并更改mysql的配置设置。Mysql需要滚动重启。通常,一个人会写一些东西,大致如下:

-模板:
src:mysql.j2
dest:/etc/mysql
注册:mysql\u config
时间:mysql.role!='仲裁人
-服务:
名称:mysql
状态:重新启动
节气门:1
什么时候:
-mysql\u config.changed
-mysql.role!='仲裁人

这种Ansible配置的缺点是,如果mysql由于任何原因无法在host2上启动,Ansible也会在host3上重新启动mysql。这是不希望的,因为如果mysql在host3上也出现故障,那么集群就会丢失。因此,对于这个特定的任务,如果mysql无法在游戏中的单个主机上启动,我想停止/中止/跳过其他任务。

解决这个问题的一个方法是使用
serial:1
运行playbook。这样,任务在主机上连续执行,一旦一个任务失败,playbook就会终止:

- name: My playbook
  hosts: all
  serial: 1
  any_errors_fatal: true
  tasks:
  - name: Always fail
    shell: /bin/false

在这种情况下,这将导致任务仅在第一台主机上执行。请注意,还有一个
order
子句,您还可以使用该子句控制主机的运行顺序:

免责声明:此答案中完全工作的部分的大部分功劳将归于服务器故障


以下是一个部分可行的想法,它只缺少一个主机。
为了演示,我特意将主机数量增加到5台

该想法基于上述文档页面中描述的
ansible\u play\u批次
ansible\u play\u主机

  • ansible\u play\u hosts\u all
    该剧的目标主机列表

  • ansible\u play\u批处理 当前播放运行中受序列限制的活动主机列表,也称为“批”。失败/无法访问的主机不被视为“活动”

这个想法,再加上您尝试使用
throttle:1
应该可以工作,但是如果没有一台主机,它就会失败,在
host2
上执行,而它应该跳过它

根据剧本:

-主机:所有
收集事实:不
任务:
-shell:/bin/false
当:“ansible_play|u batch | length==ansible_play_hosts|u all | length”
节气门:1
这就产生了重述:

PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
fatal: [host1]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.003915", "end": "2020-09-06 22:09:16.550406", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.546491", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [host2]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.004736", "end": "2020-09-06 22:09:16.844296", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.839560", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host3]
skipping: [host4]
skipping: [host5]

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host2                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host3                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host4                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host5                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
failed: [host1 -> host1] (item=host1) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.003706", "end": "2020-09-06 22:18:23.822608", "item": "host1", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:18:23.818902", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host2) 
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
changed: [host1 -> host1] => (item=host1)
failed: [host1 -> host2] (item=host2) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.004226", "end": "2020-09-06 22:20:38.038546", "failed_when_result": true, "item": "host2", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:20:38.034320", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

进一步看,我发现了一个服务器故障的例子,这似乎是制定解决方案的正确想法

与常规方式不同,我们的想法是从第一个主机开始,在该剧的所有目标主机上进行循环,因为在循环中,您可以轻松地访问前一个主机的注册事实,只要您的主机是循环的

下面是剧本:

-主机:所有
收集事实:不
任务:
-shell:/bin/false
循环:{{ansible\u play\u hosts}}”
寄存器:任务失败
当:“failing_task | default({})未失败”
委托给:“{{item}}”
跑一次:对
这将产生概述:

PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
fatal: [host1]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.003915", "end": "2020-09-06 22:09:16.550406", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.546491", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [host2]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.004736", "end": "2020-09-06 22:09:16.844296", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.839560", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host3]
skipping: [host4]
skipping: [host5]

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host2                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host3                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host4                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host5                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
failed: [host1 -> host1] (item=host1) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.003706", "end": "2020-09-06 22:18:23.822608", "item": "host1", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:18:23.818902", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host2) 
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
changed: [host1 -> host1] => (item=host1)
failed: [host1 -> host2] (item=host2) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.004226", "end": "2020-09-06 22:20:38.038546", "failed_when_result": true, "item": "host2", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:20:38.034320", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
为了证明它按预期工作,在以下方面的帮助下修改它以使
host2
特别失败:

-主机:所有
收集事实:不
任务:
-shell:/bin/false
循环:{{ansible\u play\u hosts}}”
寄存器:任务失败
当:“failing_task | default({})未失败”
委托给:“{{item}}”
跑一次:对
“项目=='host2'时失败”
总结如下:

PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
fatal: [host1]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.003915", "end": "2020-09-06 22:09:16.550406", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.546491", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
fatal: [host2]: FAILED! => {"changed": true, "cmd": "/bin/false", "delta": "0:00:00.004736", "end": "2020-09-06 22:09:16.844296", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:09:16.839560", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host3]
skipping: [host4]
skipping: [host5]

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host2                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host3                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host4                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
host5                      : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
failed: [host1 -> host1] (item=host1) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.003706", "end": "2020-09-06 22:18:23.822608", "item": "host1", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:18:23.818902", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host2) 
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
PLAY [all] ***********************************************************************************************************

TASK [shell] *********************************************************************************************************
changed: [host1 -> host1] => (item=host1)
failed: [host1 -> host2] (item=host2) => {"ansible_loop_var": "item", "changed": true, "cmd": "/bin/false", "delta": "0:00:00.004226", "end": "2020-09-06 22:20:38.038546", "failed_when_result": true, "item": "host2", "msg": "non-zero return code", "rc": 1, "start": "2020-09-06 22:20:38.034320", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
skipping: [host1] => (item=host3) 
skipping: [host1] => (item=host4) 
skipping: [host1] => (item=host5) 

NO MORE HOSTS LEFT ***************************************************************************************************

PLAY RECAP ***********************************************************************************************************
host1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
好的,这是有效的:

#请注意test-multi-01设置跳过的主机:true
---
-主持人:
-test-multi-01
-test-multi-02
-测试-03
任务:
-设定事实:
跳过的主机:“{{inventory\u hostname}”
何时:主机\u跳过了哪个\u
-shell:/bin/false
跑一次:是的
委托给:“{{item}}”
循环:{{ansible\u play\u hosts}}”
什么时候:
-项目!=主机\u跳过了哪个\u
-结果未定义或结果未失败
寄存器:结果
-梅塔:结束比赛
当:结果失败时
-调试:
味精:不会发生

当shell命令设置为
/bin/true
时,该命令将在主机2和主机3上执行。

对我来说不可能。必须将配置纳入角色中。再说一次,使用序列号是相当粗略的。而且订购该剧是没有用的……使用
run\u once
有一个很大的缺点。如果为该任务放置了另一个when子句,并且执行该任务的第一台主机应跳过该任务,则将跳过该任务本身。示例:。你能想出一些能让它起作用的方法吗?嗯,在这里,这并没有链接到
ru