控制 playbook 执行:策略及其他
默认情况下,Ansible 在任何主机上开始下一个任务之前,先在受 play 影响的所有主机上运行每个任务,使用 5 个 forks。如果您想更改此默认行为,可以使用不同的策略插件,更改 forks 的数量,或者应用诸如 serial
之类的关键字。
选择策略
上面描述的默认行为是 linear 策略。Ansible 提供了其他策略,包括 debug 策略(另请参阅 调试任务)和 free 策略,它允许每个主机尽可能快地运行到 play 结束
- hosts: all
strategy: free
tasks:
# ...
您可以为每个 play 选择不同的策略,如上所示,或者在 ansible.cfg
中全局设置您喜欢的策略,在 defaults
部分下
[defaults]
strategy = free
所有策略都实现为 策略插件。请查看每个策略插件的文档,了解其工作原理的详细信息。
设置 forks 数量
如果您有可用的处理能力并且想要使用更多的 forks,可以在 ansible.cfg
中设置数量
[defaults]
forks = 30
或者在命令行上传递它:ansible-playbook -f 30 my_playbook.yml。
使用关键字控制执行
除了策略之外,几个 关键字 也会影响 play 的执行。您可以使用 serial
设置一次要管理的主机数量(可以是数字、百分比或数字列表)。Ansible 在开始下一批主机之前,会完成指定数量或百分比的主机上的 play。您可以使用 throttle
限制分配给块或任务的工作进程数量。您可以使用 order
控制 Ansible 如何选择组中下一个要执行的主机。您可以使用 run_once
在单个主机上运行任务。这些关键字不是策略。它们是应用于 play、块或任务的指令或选项。
影响 play 执行的其他关键字包括 ignore_errors
、ignore_unreachable
和 any_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_unreachable 或 max_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
如果您已经限制了 forks 的数量或并行执行的机器数量,则可以使用 throttle
减少工作进程的数量,但无法增加它。换句话说,要产生效果,您的 throttle
设置必须低于您的 forks
或 serial
设置(如果您一起使用它们)。
基于清单排序执行
order
关键字控制主机运行的顺序。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 批次中的一个主机上运行。如果任务必须只运行一次,而不管 serial
模式如何,请使用 when: inventory_hostname == ansible_play_hosts_all[0]
结构。
注意
任何条件(换句话说,when:)都将使用“第一个主机”的变量来决定是否运行该任务,不会测试其他主机。
注意
如果你想避免为所有主机设置事实的默认行为,请为特定的任务或块设置 delegate_facts: True
。
另请参阅
- Ansible playbook
Playbook 入门
- 控制任务的运行位置:委托和本地操作
在特定机器上运行任务或将事实分配给特定机器
- 角色
按角色组织 Playbook
- 交流
有问题吗?需要帮助吗?想分享你的想法吗?请访问 Ansible 交流指南