Ansible – это мощный и простой инструмент автоматизации с открытым кодом. Он помогает оптимизировать множество задач по эксплуатации ИТ-инфраструктуры, от самых простых, наподобие установки программных пакетов, до весьма сложных, вроде развертывания кластера с несколькими узлами или многоэтапного обновления операционной системы. Сегодня мы расскажем, как оптимизировать плейбуки Ansible, чтобы создаваемые вами автоматизации работали быстрее.
Советы по оптимизации плейбуков
1. Выясните, какие задачи отнимают больше всего времени
Бывает, что та или иная задача (task) в составе плейбука выглядит простой и безобидной, но именно на нее уходит большая часть времени выполнения всего плейбука. Выявить такие задачи можно с помощью callback-плагинов, таких как timer
, profile_tasks
и profile_roles
.
Для начала включим использование этих плагинов в ansible.cfg
:
[defaults]
inventory = ./hosts
callbacks_enabled = timer, profile_tasks, profile_roles
Теперь выполним команду ansible-playbook
:
$ ansible-playbook site.yml
PLAY [Deploying Web Server] ************
TASK [Gathering Facts] **********************
Thursday 23 December 2021 22:55:58 +0800 (0:00:00.055) 0:00:00.055
Thursday 23 December 2021 22:55:58 +0800 (0:00:00.054) 0:00:00.054
ok: [node1]
TASK [Deploy Web service] *******************
Thursday 23 December 2021 22:56:00 +0800 (0:00:01.603) 0:00:01.659
Thursday 23 December 2021 22:56:00 +0800 (0:00:01.603) 0:00:01.658
...<output removed>...
PLAY RECAP **********************************
node1: ok=9 changed=4 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0
Playbook run took 0 days, 0 hours, 0 minutes, 14 seconds
Thursday 23 December 2021 22:56:12 +0800 (0:00:00.541) 0:00:14.100 *****
===============================================================================
deploy-web-server : Install httpd and firewalld ------- 5.42s
deploy-web-server : Git checkout ---------------------- 3.40s
Gathering Facts --------------------------------------- 1.60s
deploy-web-server : Enable and Run Firewalld ---------- 0.82s
deploy-web-server : firewalld permitt httpd service --- 0.72s
deploy-web-server : httpd enabled and running --------- 0.55s
deploy-web-server : Set Hostname on Site -------------- 0.54s
deploy-web-server : Delete content & directory -------- 0.52s
deploy-web-server : Create directory ------------------ 0.41s
Deploy Web service ------------------------------------ 0.04s
Thursday 23 December 2021 22:56:12 +0800 (0:00:00.541) 0:00:14.099
=====================================================================
deploy-web-server ------------------------- 12.40s
gather_facts ------------------------------- 1.60s
include_role ------------------------------- 0.04s
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
total ------------------------------------- 14.04s
Глядя на вывод этой команды, где есть время выполнения каждой задачи, роли и т.п., четко видно, какая задача отнимает больше всего времени.
2. Отключите сбор фактов
При выполнении плейбука каждая команда play с помощью модуля setup
запускает скрытую задачу gathering facts. Эта задача собирает сведения об удаленном узле, где выполняется автоматизация, и пишет их в переменную ansible_facts
. Но если вы никак не используется эти сведения в своем плейбуке, то это просто пустая трата времени. Чтобы отключить сбор фактов, достаточно прописать gather_facts: False
в play.
Для примера посмотрим статистику, когда сбор фактов включен:
$ time ansible-playbook site.yml
PLAY [Deploying Web Server] *********************
TASK [Gathering Facts] **************************
ok: [node1]
...<output removed>...
PLAY RECAP **************************************
node1: ok=9 changed=4 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0
ansible-playbook site.yml 3.03s user 0.93s system 25% cpu 15.526 total
А теперь статистика с gather_facts: False
:
$ time ansible-playbook site.yml
PLAY [Deploying Web Server] ****************
...<output removed>...
PLAY RECAP **************************************
node1: ok=8 changed=4 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0
ansible-playbook site.yml 2.96s
user 1.00s
system 26%
cpu 14.992 total
Понятно, что чем больше узлов, тем больше времени экономит отказ от сбора фактов.
3. Настройте параллельное выполнение
Ansible выполняет каждую задачу не на всех узлах сразу, а партиями. Размер партий настраивается через параметр forks
и по умолчанию равен 5. Поэтому Ansible запускает задачу на первых пяти узлах, ждет, пока она на них выполнится, затем берет следующие пять узлов и т.д. Когда задача выполнится на всех узлах, Ansible берет следующую задачу из плейбука и опять начинает выполнять ее партиями по пять узлов.
Чтобы распараллелить задачу по большему числу узлов, надо поменять значение параметра forks
в ansible.cfg
:
[defaults]
inventory = ./hosts
forks=50
Значение forks
также можно динамически менять при запуске плейбука с помощью опции --forks
(сокращенно -f
):
$ ansible-playbook site.yaml --forks 50
Примечание. Чем больше узлов, на которых Ansible выполняет задачи параллельно, тем больше ресурсов CPU и памяти ему нужно на машине, где крутится узел управления Ansible (control node). Поэтому настраивайте forks
аккуратно.
4. Оптимизируйте SSH
Установление SSH-сеанса – процесс довольно медленный, и выполняется он в фоновом режиме. Когда у вас много задач в плейбуке и много узлов, на которых они должны выполниться, общее время работы плейбука существенно увеличивается.
Бороться с этим можно с помощью параметров ControlMaster
и ControlPersist
в ansible.cfg
(секция ssh_connection
):
ControlMaster – позволяет «утрамбовать» несколько одновременных SSH-сеансов с удаленным узлом в одно сетевое подключение. Это экономит время, поскольку сетевое подключение к узлу производится только при первом SSH-сеансе, а последующие просто работают через это подключение.
ControlPersist – время, в течение которого неактивный SSH-сеанс остается открытым в фоновом режиме. Например,
ControlPersist=60s
означает, что неактивное соединение живет 60 секунд:
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
5. Отключите проверку SSH-ключей хоста в динамической среде
По умолчанию Ansible проверяет и верифицирует SSH-ключи хоста для защиты от атак с подменой сервера или man-in-the-middle. На такую проверку тоже уходит время. Если у вас полностью контролируемая среда с неизменяемыми управляемыми узлами (ВМ или контейнеры), то при переустановке или воссоздании узла его ключ будет другим. В таких средах можно отключить проверку ключей с помощью параметра host_key_checking =
False
в ansible.cfg
:
[defaults]
host_key_checking = False
Примечание. За пределами контролируемых сред отключать эту проверку очень не рекомендуется. Поэтому применяйте этот способ только когда четко понимаете, что делаете.
6. Активируйте параметр pipelining
Когда Ansible использует SSH при копировании файлов, скриптов и выполнении других команд, то в фоновом режиме выполняется ряд операций SSH. Можно уменьшить количество SSH-соединений, включив параметр pipelining (по умолчанию он отключен) в ansible.cfg
:
# ansible.cfg
pipelining = True
7. Грамотно варьируйте стратегии выполнения
По умолчанию Ansible использует линейную стратегию – ждет, пока текущая задача сценария не завершится на всех узлах, и лишь потом переходит к следующей задаче.
Если у вас нет зависимостей с привязкой к задачам или управляемым узлам, то можно изменить значение параметра strategy
на free
. Тогда Ansible будет прогонять сценарную последовательность задач на каждом узле независимо, не дожидаясь, пока каждая задача выполнится на всех узлах:
- hosts: production servers
strategy: free
tasks:
При необходимости можно разработать свои или использовать готовые плагины стратегий, такие как Mitogen с программированием подключений и выполнения на Python.
8. Используйте асинхронные задачи
При выполнении задачи Ansible дожидается ее завершения, и лишь затем закрывает соединение с управляемым узлом. Когда у вас есть долгоиграющие задачи (бэкап дисков, установка пакетов и т.д.), это может неоправданно увеличивать общее время выполнения. Если следующие задачи сценарии не зависят от этой долгой задачи, то можно использовать режим async
с соответствующим интервалом опроса poll
, чтобы Ansible не ждал завершения долгой задачи и переходил к следующим:
---
- name: Async Demo
hosts: nodes
tasks:
- name: Initiate custom snapshot
shell:
"/opt/diskutils/snapshot.sh init"
async: 120 # Maximum allowed time in Seconds
poll: 05 # Polling Interval in Seconds
Резюме
Время выполнения плейбуков Ansible зависит от множества конфигурационных параметров, оптимальные значения которых определяются спецификой конкретной ИТ-среды и применяемых в ней автоматизаций. Мы рассмотрели далеко не весь список, есть целый ряд других параметров, таких как serial
, throttle
, run_once
и других, о которых можно подробнее узнать в документации Ansible.
Комментарии (13)
ultral
11.02.2022 10:45имхо mithogen самое действенное из списка. остальное не такой эффект дает. начал пользовать его на 2.9 примерно в 19 году. на группе в 60+ хостов с немного потюненным ssh подключение.
без mithogen 28 минут 5 форков, LA ~ 2-4
с mithogen: 8 минут 70 форков LA ~ 30
щас хостов порядка 120 в той же группе, кода тоже подросло почти джоба бежит 37 минут ghb 30 форков LA ~ 10. Боюсь предположить сколько без mithogen будет
amarao
А главный кровавый трюк не описан.
pip install mitogen
. Стальной монстр, несущийся с бешенной скоростью, рельсы которого надо смазывать кровью человеков. Один раз попробуешь, отказаться нельзя (получить ускорение плейбуки с 40 минут до 18?), но иногда нужны жертвоприношения... (потому что EOF бла-бла-бла).Meklon
Расскажи? Не сталкивался раньше.
Meklon
Полистал документацию. А минусы какие?
AnyKey80lvl
Работает нормально только до версии 2.9 включительно. Далее его отключаешь и становится больно и грустно.
Alex_333
Так и есть, я вчера на 2.10.2 поэкспериментировал - да, ошибки сыпятся и жалобы на это уже почти год без ответа.
ultral
можно примеры проблем? я на ansible==2.10.7 и python 3.6.8 на 50к SLOC ямла полет нормальный.
Alex_333
Да, вот оно
Спойлер
amarao
Наоборот, новый митоген работает на 2.12, и по ощущениям, с меньшими глюками, чем на 2.9.
AnyKey80lvl
Спасибо, сподвигнули перепроверить. И вправду заработал на последних версиях митогена!
creker
Митоген по сути мёртвый проект. По всем внешним признакам и словам основных разрабов, желания и возможностей его поддерживать у них особо нет. Ансибл экосистему они в целом больше не используют. Поддержки от сообщества у проекта тоже нет. Держаться за такой проект себе дороже. Лучше отказаться как можно раньше и искать другие пути ускорения.
То, что он работает случайным образом на последний версиях, не более чем везение с учётом, что митоген по своей сути это манкипатчинг ансибла. Как говорят разрабы, поддерживать такое поделие задача не из простых в условиях, когда апстриму на них пофиг и любой релиз как хочет ломает их. Эти патчи нужно мержить в ядро ансибла, что наверное на данном этапе практически невозможно.
amarao
И это кровавый секрет ансибла. Стальной демон скорости, рельсы которого смазаны манкипатчингом и кровью невинно пострадавших. Но какая скорость...
Просто невозможно принести MR, который из 18 минут проекта сделает больше часа. Не примут. Никто не примет.
(strategy: linear позволяет затыкать кровавые дыры и ехать дальше).