控制 Playbook 执行:策略及更多

默认情况下,Ansible 会在所有受 play 影响的主机上执行完每个任务,然后再开始在任何主机上执行下一个任务,使用 5 个 fork。 如果要更改此默认行为,可以使用不同的策略插件、更改 fork 的数量,或应用几个关键字(例如 serial)。

选择策略

上述默认行为是线性策略。 Ansible 提供了其他策略,包括 调试策略 (另请参阅 调试任务) 和 自由策略,它允许每个主机尽可能快地运行到 play 的末尾。

- hosts: all
  strategy: free
  tasks:
  # ...

您可以为每个 play 选择不同的策略,如上所示,或者在 ansible.cfgdefaults 部分下全局设置您首选的策略

[defaults]
strategy = free

所有策略都实现为 策略插件。 请查看每个策略插件的文档,了解其工作原理的详细信息。

设置 Fork 数量

如果您有可用的处理能力并且想要使用更多 fork,您可以在 ansible.cfg 中设置数量

[defaults]
forks = 30

或在命令行上传递它:ansible-playbook -f 30 my_playbook.yml

使用关键字控制执行

除了策略之外,几个 关键字 也会影响 play 的执行。 您可以使用 serial 设置一次要管理的主机数量、百分比或主机数量列表。 Ansible 会在指定数量或百分比的主机上完成 play,然后再开始下一批主机。 您可以使用 throttle 限制分配给块或任务的工作人员数量。 您可以使用 order 控制 Ansible 如何选择组中下一个要执行的主机。 您可以使用 run_once 在单个主机上运行任务。 这些关键字不是策略。 它们是应用于 play、块或任务的指令或选项。

影响 play 执行的其他关键字包括 ignore_errorsignore_unreachableany_errors_fatal。 这些选项记录在 Playbook 中的错误处理中。

使用 serial 设置批处理大小

默认情况下,Ansible 会并行针对您在每个 play 的 hosts: 字段中设置的模式中的所有主机运行。 如果您想一次只管理少量机器,例如在滚动更新期间,可以使用 serial 关键字定义 Ansible 一次应管理多少主机

---
- name: test play
  hosts: webservers
  serial: 3
  gather_facts: False

  tasks:
    - name: first task
      command: hostname
    - name: second task
      command: hostname

在上面的示例中,如果我们在“webservers”组中有 6 个主机,Ansible 将在 3 个主机上完全执行 play(两个任务),然后再转移到接下来的 3 个主机

PLAY [webservers] ***********************************************************************

TASK [first task] ***********************************************************************
changed: [web1]
changed: [web3]
changed: [web2]

TASK [second task] **********************************************************************
changed: [web1]
changed: [web2]
changed: [web3]

PLAY [webservers] ***********************************************************************

TASK [first task] ***********************************************************************
changed: [web4]
changed: [web5]
changed: [web6]

TASK [second task] **********************************************************************
changed: [web4]
changed: [web5]
changed: [web6]

PLAY RECAP ******************************************************************************
web1                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web3                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web4                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web5                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web6                       : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

注意

使用 serial 设置批处理大小会将 Ansible 故障的范围更改为批处理大小,而不是整个主机列表。 您可以使用 ignore_unreachablemax_fail_percentage 来修改此行为。

您还可以使用 serial 关键字指定百分比。 Ansible 将百分比应用于 play 中主机的总数,以确定每次传递的主机数

---
- name: test play
  hosts: webservers
  serial: "30%"

如果主机数量不能平均分配到传递次数,则最后一次传递将包含剩余部分。 在此示例中,如果您在 webservers 组中有 20 个主机,则第一批将包含 6 个主机,第二批将包含 6 个主机,第三批将包含 6 个主机,最后一批将包含 2 个主机。

您还可以将批处理大小指定为列表。 例如

---
- name: test play
  hosts: webservers
  serial:
    - 1
    - 5
    - 10

在上面的示例中,第一批将包含单个主机,下一批将包含 5 个主机,并且(如果还有任何剩余主机)随后的每一批将包含 10 个主机或所有剩余主机(如果剩余主机少于 10 个)。

您可以将多个批处理大小列为百分比

---
- name: test play
  hosts: webservers
  serial:
    - "10%"
    - "20%"
    - "100%"

您还可以混合和匹配值

---
- name: test play
  hosts: webservers
  serial:
    - 1
    - 5
    - "20%"

注意

无论百分比多小,每次传递的主机数量始终为 1 或更大。

使用 throttle 限制执行

throttle 关键字限制特定任务的工作人员数量。 可以在块和任务级别设置。 使用 throttle 来限制可能占用大量 CPU 或与限速 API 交互的任务

tasks:
- command: /path/to/cpu_intensive_command
  throttle: 1

如果您已经限制了 fork 的数量或要并行执行的机器数量,您可以使用 throttle 减少工作人员数量,但不能增加。 换句话说,要生效,您的 throttle 设置必须低于您的 forksserial 设置(如果您一起使用它们)。

基于清单排序执行

order 关键字控制主机运行的顺序。 顺序的可能值为

inventory

(默认)清单为所请求的选择提供的顺序(请参阅下面的注释)

reverse_inventory

与上述相同,但反转返回的列表

sorted

按名称按字母顺序排序

reverse_sorted

按名称以反向字母顺序排序

shuffle

每次运行随机排序

注意

“inventory”顺序不等同于主机/组在清单源文件中定义的顺序,而是“从编译清单返回选择的顺序”。 这是一个向后兼容的选项,虽然可重现,但通常是不可预测的。 由于清单的性质、主机模式、限制、清单插件以及允许使用多个源的能力,几乎不可能返回这样的顺序。 对于简单的情况,这可能与文件定义顺序匹配,但不能保证。

使用 run_once 在单个机器上运行

如果您希望任务仅在批处理中的第一个主机上运行,请将该任务上的 run_once 设置为 true

---
# ...

  tasks:

    # ...

    - command: /opt/application/upgrade_db.py
      run_once: true

    # ...

Ansible 会在当前批次中的第一个主机上执行此任务,并将所有结果和事实应用到同一批次中的所有主机。这种方法类似于将条件应用于任务,例如

- command: /opt/application/upgrade_db.py
  when: inventory_hostname == webservers[0]

但是,使用 run_once 时,结果会应用于所有主机。要在特定主机上运行任务,而不是在批次的第一个主机上运行,请委托该任务。

- command: /opt/application/upgrade_db.py
  run_once: true
  delegate_to: web01.example.org

委托 一样,该操作将在委托主机上执行,但信息仍然是任务中原始主机的信息。

注意

当与 serial 一起使用时,标记为 run_once 的任务将在每个串行批次中的一个主机上运行。如果任务必须只运行一次,而不管 serial 模式如何,请使用 when: inventory_hostname == ansible_play_hosts_all[0] 结构。

注意

任何条件(换句话说,when:)都将使用“第一个主机”的变量来决定是否运行该任务,不会测试其他主机。

注意

如果您想避免为所有主机设置事实的默认行为,请为特定任务或块设置 delegate_facts: True

另请参阅

Ansible Playbook

Playbook 简介

控制任务的运行位置:委托和本地操作

在特定机器上运行任务或将事实分配给特定机器

角色

按角色组织 Playbook

通信

有问题?需要帮助?想分享你的想法?请访问 Ansible 通信指南