Асинхронные действия и опрос
По умолчанию 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 не поддерживает режим проверки и завершит задачу при запуске в режиме проверки. Смотрите Проверка задач: режим проверки и режим diff о том, как пропустить задачу в режиме проверки.
Примечание
По завершении асинхронной задачи с включённым опросом временный кэш асинхронного задания (по умолчанию в ~/.ansible_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 ускорит запуск асинхронных задач. Это также повышает эффективность опроса.
Примечание
При выполнении с poll: 0, Ansible не будет автоматически очищать кэш асинхронных заданий. Вам необходимо будет вручную очистить его с помощью модуля async_status с mode: cleanup.
Если вам нужна точка синхронизации с асинхронной задачей, вы можете зарегистрировать её, чтобы получить её идентификатор задания, и использовать модуль 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
-
Введение в плейбуки
- Связь
-
Есть вопросы? Нужна помощь? Хотите поделиться идеями? Посетите руководство по общению с Ansible
© 2012–2018 Michael DeHaan
© 2018–2024 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_async.html