Управление выполнением плейбуков: стратегии и не только
По умолчанию Ansible выполняет каждую задачу на всех хостах, затронутых плейбуком, прежде чем перейти к следующей задаче на любом хосте, используя 5 форков. Чтобы изменить это поведение по умолчанию, можно использовать другой плагин стратегии, изменить количество форков или применить одно из нескольких ключевых слов, например serial.
Выбор стратегии
Описанное выше поведение по умолчанию называется линейной стратегией. Ansible предлагает и другие стратегии, включая стратегию отладки (см. также Отладка задач) и свободную стратегию, которая позволяет каждому хосту выполнять задачи до конца плейбука с максимально возможной скоростью:
- hosts: all strategy: free tasks: # ...
Как показано выше, для каждого плейбука можно выбрать другую стратегию или задать предпочтительную стратегию глобально в ansible.cfg, в секции defaults:
[defaults] strategy = free
Все стратегии реализованы в виде плагинов стратегии. Подробнее о работе каждой стратегии см. в документации к соответствующему плагину.
Настройка количества форков
Если у вас достаточно вычислительных ресурсов и вы хотите использовать больше форков, задайте их количество в ansible.cfg:
[defaults] forks = 30
или передайте это значение в командной строке: ansible-playbook -f 30 my_playbook.yml.
Управление выполнением с помощью ключевых слов
Помимо стратегий на выполнение плейбука влияют и некоторые ключевые слова. С помощью serial можно задать количество, процент или список чисел хостов, которыми нужно управлять одновременно. Ansible завершает выполнение плейбука на заданном количестве или проценте хостов, прежде чем перейти к следующему пакету хостов. С помощью throttle можно ограничить количество рабочих процессов, выделенных блоку или задаче. С помощью order можно управлять выбором следующего хоста в группе для выполнения задачи. С помощью run_once можно выполнить задачу на одном хосте. Эти ключевые слова не являются стратегиями. Это директивы или параметры, применяемые к плейбуку, блоку или задаче.
К другим ключевым словам, влияющим на выполнение плейбука, относятся ignore_errors, ignore_unreachable и any_errors_fatal. Эти параметры описаны в разделе Обработка ошибок в плейбуках.
Настройка размера пакета с помощью serial
По умолчанию Ansible выполняет задачи параллельно на всех хостах, соответствующих шаблону, заданному в поле 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 хостах, прежде чем перейти к следующим 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 применяет этот процент к общему количеству хостов в плейбуке, чтобы определить количество хостов за один проход:
--- - 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%"
Примечание
Независимо от того, насколько мал процент, в каждом проходе всегда будет обрабатываться не менее одного хоста.
Ограничение выполнения с помощью throttle
Ключевое слово throttle ограничивает количество рабочих процессов для конкретной задачи. Его можно задать на уровне блока или задачи. Используйте throttle для ограничения задач, которые могут сильно нагружать процессор или взаимодействуют с API, ограничивающим частоту запросов:
tasks: - command: /path/to/cpu_intensive_command throttle: 1
Если вы уже ограничили количество форков или количество компьютеров, на которых задачи выполняются параллельно, с помощью 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, используйте конструкцию when: inventory_hostname == ansible_play_hosts_all[0].
Примечание
Любое условие (иначе говоря, when:) будет использовать переменные «первого хоста», чтобы определить, запускать ли задачу; остальные хосты проверяться не будут.
Примечание
Чтобы избежать поведения по умолчанию, при котором факт задаётся для всех хостов, установите delegate_facts: True для конкретной задачи или блока.
См. также
- Плейбуки Ansible
-
Введение в плейбуки
- Управление местом выполнения задач: делегирование и локальные действия
-
Выполнение задач на определённых компьютерах или назначение им фактов
- Роли
-
Организация плейбуков с помощью ролей
- Общение
-
Есть вопросы? Нужна помощь? Хотите поделиться идеями? Посетите руководство по общению Ansible
© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_strategies.html