我在 ansible 中一直遇到的一个问题是,当多个准备步骤中的任何一个已经完成时,应该运行哪个部署步骤?已更改, 但这已更改状态丢失,原因是致命的错误。
当一个准备步骤成功完成后,ansible 无法继续,我仍然希望机器最终达到剧本想要达到的状态。但是 ansible 忘记了,例如:
- name: "(a) some task is changed"
git:
update: yes
...
notify:
# (b) ansible knows about having to call handler later!
- apply
- name: "(c) connection lost here"
command: ...
notify:
- apply
- name: apply
# (d) handler never runs: on the next invocation git-fetch is a no-op
command: /bin/never
由于准备步骤(A)现在是无操作,再次运行不会恢复此信息。对于某些任务,只需运行所有处理程序就足够了。对于其他任务,可以将处理程序重写为知道when:
要运行的任务。但有些任务和检查很昂贵和/或不可靠,所以这并不总是足够好。
部分解决方案:
- 写出一个文件,稍后再检查它是否存在,而不是依赖于 ansible处理程序。这感觉像是一种反模式。毕竟,ansible 知道剩下要做什么——我只是不知道如何让它在多次尝试中记住它。
- 保持循环直到它工作或应用手动修复,无论多长时间:这似乎是一个糟糕的交易,因为现在我可能无法对同一组目标使用 ansible ..或者我必须防止多次并发运行产生不良的副作用
- 只需要更高的目标可靠性,因此它足够罕见,以证明总是手动解决这些情况,使用
--start-at-task=
和检查仍然需要哪些处理程序:经验表明,事情偶尔会中断,现在我正在添加更多可能发生故障的事情。
是否有某种模式、特征或技巧适当地如何处理此类错误?
答案1
您链接的 Ansible 文档建议解决这个问题的方法:
Ansible 运行处理程序在每个剧本结束时。如果一个任务通知处理程序,但剧本中稍后的另一个任务失败,则默认情况下处理程序会不是在该主机上运行,这可能会导致主机处于意外状态。例如,任务可以更新配置文件并通知处理程序重新启动某些服务。如果同一剧集中稍后的任务失败,则配置文件可能会更改,但服务不会重新启动。
您可以使用
--force-handlers
命令行选项更改此行为,方法是将其包含force_handlers: True
在 play 中或添加force_handlers = True
到 ansible.cfg 中。强制使用处理程序时,Ansible 将在所有主机上运行所有通知的处理程序,即使是任务失败的主机也是如此。(请注意,某些错误仍可能阻止处理程序运行,例如主机变得无法访问。)
将其放置在 ansible.cfg 中将确保它是您运行的每个剧本和角色的默认行为。
如果主机在剧本运行期间死亡,几乎没有什么可以拯救你。
答案2
目前看来,解决这个问题的唯一方法就像 Michael Hampton 指出的那样。
在我看来这不是一个可行的解决方案,因为处理程序本身可能会因源错误而导致错误,从而导致剧本运行崩溃。更好的解决方案应该在剧本执行之间保留处理程序通知状态,最好是在远程主机上。已经有了事实和习惯事实它保存远程主机磁盘上的某种状态。
目前我还不知道该如何实现这一点。