Асинхронные действия и опрос
По умолчанию 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, передав ему идентификатор задания, который был возвращен при запуске исходного задания в фоновом режиме:
$ 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) процесс на удаленных узлах будет завершен.
Асинхронный режим лучше всего подходит для длительных команд оболочки или обновлений программного обеспечения. Например, запуск модуля копирования в асинхронном режиме не выполняет фоновый перенос файла.
Асинхронные задачи плейбука
Плейбуки также поддерживают асинхронный режим и опрос с упрощенным синтаксисом. Вы можете использовать асинхронный режим в плейбуках, чтобы избежать таймаутов соединения или чтобы не блокировать последующие задачи. Поведение асинхронного режима в плейбуке зависит от значения 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 не поддерживает режим проверки и завершит задачу при запуске в режиме проверки. Смотрите Проверка задач: режим проверки и режим сравнения для информации о пропуске задачи в режиме проверки.
Выполнение задач одновременно: poll = 0
Если вы хотите выполнить несколько задач в плейбуке одновременно, используйте async со значением poll равным 0. При установке poll: 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
Примечание
Не указывайте значение poll равное 0 для операций, требующих эксклюзивных блокировок (таких как операции yum), если вы ожидаете выполнения других команд позже в плейбуке с теми же ресурсами.
Примечание
Использование более высокого значения для --forks приведет к ещё более быстрому запуску асинхронных задач. Это также повышает эффективность опроса.
Если вам нужна точка синхронизации с асинхронной задачей, вы можете зарегистрировать её для получения 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:, не будет создан или больше не существует.
Для выполнения нескольких асинхронных задач, ограничивая количество одновременно выполняемых задач:
#####################
# 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
См. также
- Управление выполнением плейбука: стратегии и многое другое
-
Варианты управления выполнением плейбука
- Введение в плейбуки
-
Введение в плейбуки
- Пользовательская рассылка
-
Есть вопросы? Зайдите на форум 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.10/user_guide/playbooks_async.html