异步操作和轮询
默认情况下,Ansible 同步运行任务,在操作完成之前保持与远程节点的连接。这意味着在剧本中,默认情况下每个任务都会阻塞下一个任务,后续任务只有在当前任务完成之后才能运行。这种行为可能会带来挑战。例如,一个任务可能需要比 SSH 会话允许的时间更长才能完成,从而导致超时。或者您可能希望在同时执行其他任务时,让一个长时间运行的进程在后台执行。异步模式使您能够控制长时间运行的任务的执行方式。
异步 ad hoc 任务
您可以使用 ad hoc 任务 在后台执行长时间运行的操作。例如,要异步在后台执行 long_running_operation
,并设置超时(-B
)为 3600 秒,且不进行轮询(-P
)
$ ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
要稍后检查作业状态,请使用 async_status
模块,并向其传递在后台运行原始作业时返回的作业 ID
$ ansible web1.example.com -m async_status -a "jid=488359678239.2844"
Ansible 还可以使用轮询自动检查长时间运行作业的状态。在大多数情况下,Ansible 会在轮询之间保持与远程节点的连接。要运行 30 分钟并每 60 秒轮询一次状态
$ ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
轮询模式非常智能,因此所有作业将在任何机器上开始轮询之前启动。如果您希望非常快地启动所有作业,请确保使用足够高的 --forks
值。当时间限制(以秒为单位)到期(-B
)后,远程节点上的进程将被终止。
异步模式最适合长时间运行的 shell 命令或软件升级。例如,异步运行 copy 模块不会执行后台文件传输。
异步剧本任务
剧本 也支持异步模式和轮询,语法更简化。您可以在剧本中使用异步模式来避免连接超时或避免阻塞后续任务。剧本中异步模式的行为取决于 poll 的值。
避免连接超时:poll > 0
如果您希望为剧本中的某个特定任务设置更长的超时限制,请使用 async
,并将 poll
设置为正值。Ansible 仍然会阻塞剧本中的下一个任务,等待异步任务完成、失败或超时。但是,该任务只有在超过您使用 async
参数设置的超时限制时才会超时。
要避免任务超时,请指定其最大运行时间以及您希望轮询状态的频率
---
- hosts: all
remote_user: root
tasks:
- name: Simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec
ansible.builtin.command: /bin/sleep 15
async: 45
poll: 5
注意
默认轮询值由 DEFAULT_POLL_INTERVAL 设置决定。异步时间限制没有默认值。如果您省略 'async' 关键字,该任务将同步运行,这是 Ansible 的默认设置。
注意
从 Ansible 2.3 开始,async 不支持检查模式,并在检查模式下运行时导致任务失败。有关如何在检查模式下跳过任务的说明,请参阅 验证任务:检查模式和差异模式。
注意
当异步任务在启用轮询的情况下完成时,临时异步作业缓存文件(默认情况下位于 ~/.ansible_async/)会自动删除。
并发运行任务:poll = 0
如果您希望在剧本中并发运行多个任务,请使用 async
,并将 poll
设置为 0。当您将 poll: 0
设置为 0 时,Ansible 会启动该任务,然后立即继续执行下一个任务,而无需等待结果。每个异步任务都会一直运行,直到完成、失败或超时(运行时间超过其 async
值)。剧本运行结束,不会检查异步任务的状态。
要异步运行剧本任务
---
- hosts: all
remote_user: root
tasks:
- name: Simulate long running op, allow to run for 45 sec, fire and forget
ansible.builtin.command: /bin/sleep 15
async: 45
poll: 0
注意
如果您希望稍后在剧本中对那些相同的资源运行其他命令,请不要对需要独占锁的操作(例如 yum 事务)指定 0 的轮询值。
注意
使用更高的 --forks
值会导致更快地启动异步任务。这也提高了轮询的效率。
注意
在使用 poll: 0
运行时,Ansible 不会自动清理异步作业缓存文件。您需要使用带有 mode: cleanup
的 async_status 模块手动清理此文件。
如果您需要与异步任务进行同步,可以将其注册以获取其作业 ID,然后使用 async_status 模块在后续任务中观察它。例如
- name: Run an async task
ansible.builtin.yum:
name: docker-io
state: present
async: 1000
poll: 0
register: yum_sleeper
- name: Check on an async task
async_status:
jid: "{{ yum_sleeper.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 100
delay: 10
注意
如果 async:
的值不足够高,这将导致“稍后检查”任务失败,因为 async_status:
正在查找的临时状态文件尚未写入或不再存在。
注意
异步剧本任务始终返回已更改。如果该任务使用需要用户使用 changed_when
、creates
等来注释更改的模块,则应将它们添加到以下 async_status
任务中。
要同时运行多个异步任务,同时限制并发运行的任务数量
#####################
# main.yml
#####################
- name: Run items asynchronously in batch of two items
vars:
sleep_durations:
- 1
- 2
- 3
- 4
- 5
durations: "{{ item }}"
include_tasks: execute_batch.yml
loop: "{{ sleep_durations | batch(2) | list }}"
#####################
# execute_batch.yml
#####################
- name: Async sleeping for batched_items
ansible.builtin.command: sleep {{ async_item }}
async: 45
poll: 0
loop: "{{ durations }}"
loop_control:
loop_var: "async_item"
register: async_results
- name: Check sync status
async_status:
jid: "{{ async_result_item.ansible_job_id }}"
loop: "{{ async_results.results }}"
loop_control:
loop_var: "async_result_item"
register: async_poll_results
until: async_poll_results.finished
retries: 30
另请参阅
- 控制剧本执行:策略等
控制剧本执行的选项
- Ansible 剧本
剧本简介
- 用户邮件列表
有问题?欢迎访问 Google 群组!
- 实时聊天
如何加入 Ansible 聊天频道