【问题标题】:How to terminate an Ansible playbook run when it is successful on one host?如何在一台主机上成功终止 Ansible playbook 运行?
【发布时间】:2017-07-11 14:17:15
【问题描述】:

我有一个包含多个主机的系统以确保可用性。我只需要在一台主机上运行我的 Ansible playbook。但是,其中一些主机可能无法访问。假设我有 host1、host2、host3 ... 如果无法访问 host1,我希望 Ansible 尝试使用 host2。如果 host2 可以访问并且 Ansible 成功运行了一些 bash 脚本,我希望 Ansible 跳过其余的主机。有什么建议吗?

【问题讨论】:

  • 如何定义“成功运行一些bash脚本”中的“some”?
  • 你如何定义“无法到达”? Ansible 会自动跳过 ssh 无法访问的主机。
  • @sm4rk0 我很好奇它会如何影响答案?是否继续尝试或停止的唯一决定因素是成功执行(神秘的“某些”脚本)。在您看来,“无法到达”的定义对答案有什么作用?
  • @techraf 你是对的。我误解了这个问题。

标签: ansible


【解决方案1】:

这可能不是最佳解决方案,但我找不到更好的解决方案。

  • (可选)将gather_facts 设置为False,以完全跳过需要跳过的主机(如果您不需要收集主机事实)。
  • serial 设置为 1,因此剧本一次完全在一台主机上播放,而不是默认的 5 台主机并行播放。
  • 使用set_fact 将主机事实(例如名为done)设置为True 在播放结束时,或使用register,如果您需要更具体的条件(命令输出)。
  • 在播放开始时使用end_play meta,当变量设置为True(或具有预期值,如果您使用register)时将执行任何主机。我使用Jinja2 template language 以这种方式提取值:
    1. for 循环遍历所有 hostvars(包含为清单中所有主机设置的所有变量的 Python 字典)。
    2. if 检查主机是否将done 变量设置为True,如果是则返回字符串True
    3. default 过滤器在没有为主机定义 done 时设置默认值(这会导致错误 'dict object' has no attribute 'done')。

例如:

- hosts: all
  serial: 1
  gather_facts: False

  tasks:
  - meta: end_play
    when: "{% for item in hostvars.values() %}{% if item.done|default(False) %}True{% endif %}{% endfor %}"

  # The rest of the play goes here

  - set_fact:
      done: True

【讨论】:

    【解决方案2】:

    Ansible 不考虑那些不可访问的主机,在设置阶段不可访问的主机列表将被删除。

    在剩余的主机列表中,对该 bash 脚本的特定任务使用“run_once: yes”。它将从可用主机中选择第一个匹配的主机。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      相关资源
      最近更新 更多