在 Ansible 中重试紧密耦合的任务组
在某些情况下,处理分布式系统故障的最佳方法是重试。在使用 Ansible 配置一组机器时,同样的想法也适用。举例来说,我们有一个任务,由于某些竞争条件,10% 的主机在第一次尝试时可能并不总是成功。但是,在第二次尝试任务时,剩余 10% 的主机将成功。现在我们可以尝试以多种方式解决这种竞争条件,但有时我们可能没有时间或需要对系统进行控制来这样做。在这种情况下,重试任务可能是解决问题的最简单、最有效
在某些情况下,处理分布式系统故障的最佳方法是重试。在使用 Ansible 配置一组机器时,同样的想法也适用。举例来说,我们有一个任务,由于某些竞争条件,10% 的主机在第一次尝试时可能并不总是成功。但是,在第二次尝试任务时,剩余 10% 的主机将成功。现在我们可以尝试以多种方式解决这种竞争条件,但有时我们可能没有时间或需要对系统进行控制来这样做。在这种情况下,重试任务可能是解决问题的最简单、最有效的方法。
我在使用 Ansible 配置服务器机架时遇到了这个问题。通常,如果一个任务在第一次尝试时可能会失败,那么使用 Ansible,可以像这样重复该任务:
- name: Some task that might fail
failing_task:
some: setting
register: outcome
retries: 3
delay: 10
until: outcome.result == 'success'
进入全屏模式 退出全屏模式
这很棒!现在 Ansible 将重复该任务 3 次,每次尝试之间有 10 秒的延迟。在每次尝试结束时,都会评估until
条件,如果它不评估为真,则将重复该任务,假设仍有重试次数。
现在,假设我有一组任务需要在失败时重复,而不仅仅是上面示例中的一个。好吧,在 Ansible 中可以对任务进行分组,所以也许这会起作用:
---
- name: Group of tasks that are tightly coupled
block:
- name: Setup for the next task that needs to run after each failed attempt
setting_up:
some: prerequisite action
- name: Some task that might fail
failing_task:
some: setting
register: outcome
retries: 3
delay: 10
until: outcome.result == 'success'
进入全屏模式 退出全屏模式
不幸的是,这将不起作用,因为Ansible 目前不支持在block
上使用重试。如果您发现自己需要重复一组任务,这将起作用:
# filename: coupled_task_group.yml
- name: Group of tasks that are tightly coupled
block:
- name: Increment the retry count
set_fact:
retry_count: "{{ 0 if retry_count is undefined else retry_count | int + 1 }}"
- name: Setup for the next task that needs to run after each failed attempt
setting_up:
some: prerequisite action
- name: Some task that might fail
failing_task:
some: setting
rescue:
- fail:
msg: Maximum retries of grouped tasks reached
when: retry_count | int == 5
- debug:
msg: "Task Group failed, let's give it another shot"
- include_task: coupled_task_group.yml
进入全屏模式 退出全屏模式
乍一看,这看起来很奇怪。你可能会问,为什么block
的rescue
会调用声明任务的任务文件。我们正在使用递归的力量重复一个任务,直到达到某个条件:要么任务在第一次尝试时成功,要么重试时,或者rescue
块被调用多达五次,触发fail
任务上的when
条件,使我们退出循环。请注意,在编写任何类型的递归函数时,确保基本情况至关重要,否则函数可能会无限调用自身。当在 Ansible 中使用上述重复任务组的方法时也是如此,如果我们忘记在每次通过 Ansible 时递增retry_count
变量,则会无限期地运行直到被用户停止。
将来,应该不需要这种方法,因为将这个功能添加到 Ansible 的 PR 即将完成。要查看它是否已合并,请在此处检查。
更多推荐
所有评论(0)