Асинхронные действия и опрос
По умолчанию задачи в плейбуках блокируют выполнение, то есть соединения остаются открытыми до завершения задачи на каждом узле. Это не всегда желательно, или же вы выполняете операции, которые занимают больше времени, чем таймаут SSH.
Чтобы избежать проблем с блокировкой или таймаутами, вы можете использовать асинхронный режим для выполнения всех задач сразу, а затем опрашивать их статус до завершения.
Поведение асинхронного режима зависит от значения poll.
Избегание таймаутов соединения: poll > 0
Когда poll имеет положительное значение, плейбук по-прежнему будет блокироваться задачей до ее завершения, неудачи или таймаута.
В этом случае, однако, async явным образом устанавливает таймаут для этой задачи, а не ограничивается таймаутом метода соединения.
Чтобы запустить задачу асинхронно, укажите максимальное время её выполнения и частоту опроса статуса. Значение опроса по умолчанию составляет 15 секунд, если вы не укажете значение для poll.
---
- hosts: all
remote_user: root
tasks:
- name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec
command: /bin/sleep 15
async: 45
poll: 5
Примечание
Нет значения по умолчанию для лимита асинхронного времени. Если вы опускаете ключевое слово «async», задача выполняется синхронно, что является по умолчанию в Ansible.
Примечание
Начиная с Ansible 2.3, async не поддерживает режим проверки и завершит задачу при запуске в режиме проверки. См. Режим проверки («сухой запуск») о том, как пропустить задачу в режиме проверки.
Конкурентные задачи: poll = 0
Когда poll равно 0, Ansible запустит задачу и сразу перейдет к следующей, не дожидаясь результата.
С точки зрения последовательности это асинхронное программирование: задачи теперь могут выполняться одновременно.
Выполнение плейбука завершится без проверки асинхронных задач.
Асинхронные задачи будут выполняться до тех пор, пока не завершатся, не завершатся с ошибкой или не истечет время ожидания в соответствии с их значением async.
Если вам нужна точка синхронизации с задачей, зарегистрируйте её, чтобы получить её идентификатор задачи, и используйте модуль async_status, чтобы наблюдать за ней.
Вы можете запустить задачу асинхронно, указав значение poll в 0:
---
- hosts: all
remote_user: root
tasks:
- name: simulate long running op, allow to run for 45 sec, fire and forget
command: /bin/sleep 15
async: 45
poll: 0
Примечание
Не следует пытаться запустить задачу асинхронно, указав значение poll в 0 с операциями, требующими взаимных исключений (например, транзакции yum), если вы ожидаете выполнить другие команды в плейбуке с теми же ресурсами.
Примечание
Использование более высокого значения для --forks приведет к ещё более быстрому запуску асинхронных задач. Это также повышает эффективность опроса.
Если вы хотите выполнить задачу асинхронно и проверить её позже, вы можете выполнить задачу, подобную следующей:
---
# Requires ansible 1.8+
- name: 'YUM - async task'
yum:
name: docker-io
state: present
async: 1000
poll: 0
register: yum_sleeper
- name: 'YUM - check on async task'
async_status:
jid: "{{ yum_sleeper.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30
Примечание
Если значение async: недостаточно велико, это приведёт к неудаче задачи «проверьте позже», потому что временный файл статуса, который ищет 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
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
См. также
- Работа с плейбуками
- Введение в плейбуки
- Список рассылки пользователей
- У вас есть вопрос? Загляните в группу Google!
- irc.freenode.net
- IRC-чат-канал #ansible
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.8/user_guide/playbooks_async.html