Ansible教程——errors处理

2 篇文章 1 订阅
1 篇文章 0 订阅

Playbook中的错误处理

摘要

当Ansible从一个命令接收到一个非零的返回码或从一个模块接收到一个故障时,默认情况下它会停止在该主机上执行,并在其他主机上继续执行。

然而,在某些情况下,您可能需要不同的行为。有时,非零返回码表示成功。有时,您希望一台主机上的故障停止所有主机上的执行。Ansible提供了处理这些情况的工具和设置,并帮助您获得所需的行为、输出和报告。

  • Ignoring failed commands 忽略命令失败
  • Ignoring unreachable host errors 忽略不可达的主机错误
  • Resetting unreachable hosts 重新设置不可到达的主机
  • Handlers and failure 处理程序和失败
  • Defining failure 定义失败
  • Defining “changed”定义“改变”
  • Ensuring success for command and shell 确保成功的命令和shell
  • Aborting a play on all hosts 在所有主机上终止一个play
    • Aborting on the first error: any_errors_fatal 在第一个错误时中止:any_errors_fatal
    • Setting a maximum failure percentage 设置最大失败百分比
  • Controlling errors in blocks 在blocks区块上控制errors

一、 忽略命令失败

默认情况下,当主机上的任务失败时,Ansible会停止执行该主机上的任务。使用ignore_errors,即使碰到任务失败,仍会继续下面的任务:

- name: Do not count this as a failure
  shell: /bin/false
  ignore_errors: yes

ignore_errors指令仅在任务能够运行并返回值为failed时有效。它不会使Ansible忽略未定义的变量错误、连接失败、执行问题(例如,丢失包)或语法错误。

二、忽略不可达的主机错误

您可以使用ignore_unreachable关键字忽略由于主机实例为UNREACHABLE 而导致的任务失败。Ansible忽略任务错误,但继续对不可达的主机执行后续的任务。

1)在task中使用:

# task1中忽略不可达的主机继续执行;task2不忽略不可达主机,且该不可达主机终止执行
tasks:
    - name: task1
      command: /bin/true
      ignore_unreachable: yes

    - name: task2
      command: /bin/true
 

2)在play中使用:

# 所有tasks忽略不可达的主机,task1:忽略不可达主机继续执行play,tasks2:不忽略不可达主机且该不可达主机终止执行
- hosts: all
  ignore_unreachable: yes
  tasks:
     - name: task1
       command: /bin/true

     - name: task2
       command: /bin/true
       ignore_unreachable: no

三、重新设置不可到达的主机

如果Ansible无法连接到某个主机,它会将该主机标记为unreachable,并将其从运行的活动主机列表中删除。您可以使用meta: clear_host_errors重新激活所有主机,以便后续任务可以尝试再次访问它们。

四、处理程序和失败

如果一个任务通知了一个handler ,但另一个任务在稍后的运行中失败,默认情况下handler 不会在该主机上运行,这可能会使主机处于意外状态。

例如,一个任务可以更新配置文件并通知handler 重新启动某些服务。如果同一task中稍后的任务失败,则可能只会更改配置文件,而不会重新启动服务。

你可以通过--force-handlers命令行选项来改变这种行为,方法是在play中包含force_handlers: True,或者在ansible.cfg中添加force_handlers = True
handler 被强制执行时,Ansible将在所有主机上运行所有通知的handler ,甚至是任务失败的主机。

(注意,某些错误仍然会阻止处理程序运行,比如主机变得不可访问。)

五、定义失败

Ansible允许你在每个任务中使用failed_when条件定义“failure”的含义。

多个failed_when条件的列表使用隐式的and连接,这意味着任务只有在满足所有条件时才会失败。如果希望在满足任何条件时触发失败,则必须使用显式或操作符在字符串中定义条件。

  • 您可以通过在命令的输出中搜索一个单词或短语来检查是否失败:
- name: Fail task when the command error output prints FAILED
  command: /usr/bin/example-command -x -y -z
  register: command_result
  failed_when: "'FAILED' in command_result.stderr"
  • 基于返回码:
- name: Fail task when both files are identical
  raw: diff foo/file1 bar/file2
  register: diff_cmd
  failed_when: diff_cmd.rc == 0 or diff_cmd.rc >= 2
  • 还可以组合多个失败条件。如果两个条件都为真,该任务将失败:
# 检查某个文件是否存在
- name: Check if a file exists in temp and fail task if it does
  command: ls /tmp/file1
  register: result
  failed_when:
   - result.rc == 0
   - '"No such" not in result.stdout'
  
# 如果你想让任务在只满足任何一个条件时失败,将failed_when的定义修改为:
  failed_when: result.rc == 0 or "No such" not in result.stdout
  • 如果有太多的条件不能整齐地放在一行中,可以使用“>”将其分割为多行yaml值:
- name: example of many failed_when conditions with OR
  shell: "./myBinary"
  register: ret
  failed_when: >
    ("No such file or directory" in ret.stdout) or
    (ret.stderr != '') or
    (ret.rc == 10)

六、定义“改变”

Ansible允许你使用条件changed_when来定义一个特定的任务何时“changed”了一个远程节点。这让您可以根据返回代码或输出来决定是否应该在Ansible统计中报告更改,以及是否应该触发处理程序。

与Ansible中的所有条件一样,多个changed_when条件的列表使用隐式的“and”连接,这意味着任务只在满足所有条件时报告更改。

  • 如果希望在满足任何条件时报告更改,则必须使用显式“or“在字符串中定义条件。例如:
tasks:
  - name: Report 'changed' when the return code is not equal to 2
    shell: /usr/bin/billybass --mode="take me to the river"
    register: bass_result
    changed_when: "bass_result.rc != 2"

 - name: This will never report 'changed' status
   shell: wall 'beep'
   changed_when: False

 
  • 你也可以组合多个条件来覆盖" changed "结果:
- name: Combine multiple conditions to override 'changed' result
  command: /bin/fake_command
  register: result
  ignore_errors: True
  changed_when:
    -'"ERROR" in result.stderr'
    -result.rc == 2

七、 确保命令和shell成功

commandshell模块关心返回码,所以如果你有一个成功退出码不为零的命令,你可以这样做:

tasks:
  - name: Run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true
    

八、在所有主机上终止一个play

有时,您希望单个主机或一定百分比的主机出现failure,从而中止所有主机上的整个play。使用any_errors_fatal可以在第一次失败发生后停止play执行。对于更细粒度的控制,您可以使用max_fail_percentage在给定百分比的主机失败后中止运行。

  • 在第一个错误时中止:any_errors_fatal

如果你设置了any_errors_fatal并且一个任务返回了一个错误,Ansible会在当前批处理的所有主机上完成致命任务,然后停止在所有主机上执行剧本。后续的任务和剧本不会被执行。你可以在play或block级别设置any_errors_fatal:

- hosts: somehosts
  any_errors_fatal: true
  roles:
    -myrole 

通过向块中添加一个拯救部分,可以从致命错误中恢复运行。

- hosts: somehosts
  tasks:
  - block:
    -include_tasks: mytasks.yml
  any_errors_fatal: true

当所有任务必须100%成功才能继续执行剧本时,您可以使用此特性。例如,如果您在多个数据中心的机器上运行一个服务,使用负载平衡器将流量从用户传递到服务,那么您希望在停止服务进行维护之前禁用所有负载平衡器。为了确保任务中任何禁用负载均衡器的失败都会停止所有其他任务:

---

- hosts: load_balancers_dc_a
  any_errors_fatal: true
  tasks:
    - name: Shut down datacenter 'A'
      command: /usr/bin/disable-dc

- hosts: frontends_dc_a
  tasks:
    - name: Stop service
      command: /usr/bin/stop-software

    - name: Update software
      command: /usr/bin/upgrade-software
    
- hosts: load_balancers_dc_a
  tasks:
     - name: Start datacenter 'A'
     command: /usr/bin/enable-dc

在这个例子中,只有当所有的负载均衡器都被成功禁用时,Ansible才会在前端启动软件升级。

  • 设置最大失败百分比:max_fail_percentage

默认情况下,只要有主机没有发生故障,Ansible就会继续执行任务。在某些情况下,例如在执行滚动更新时,当达到一定的失败阈值时,您可能想要中止play。为了实现这一点,你可以设置play的最大失败百分比:

---
- hosts: webservers
  max_fail_percentage: 30
  serial: 10

max_fail_percentage设置在与serial一起使用时适用于每个批处理。在上面的例子中,如果第一批(或任何一批)服务器中的10个服务器中有3个以上失败,那么剩下的play将被中止。

九、在block上处理错误

此处详细信息可参阅《 block》。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值