Ansible с нуля: от первого плейбука до управления парком серверов
Я, Семёнов Евгений Сергеевич, директор АйТи Фреш, за 15 лет в IT повидал всякое. Могу с уверенностью сказать: круче Ansible инструмента для автоматизации я не встречал. Вы только представьте — никаких агентов на клиентских машинах! Он прекрасно общается по обычному SSH, а все настройки делаются на понятном языке YAML. Да что там говорить, любой системный администратор буквально за три рабочих вечера освоит написание плейбуков. А потом? Эти плейбуки способны накатить типовую конфигурацию на целых 50 серверов всего за пять минут! Это же просто космос по сравнению с тремя рабочими днями утомительного кликанья в PuTTY. Хотите узнать, как мы это делаем на абсолютно реальных примерах?
Что такое Ansible и чем он отличается от аналогов
Так вот, как это работает? Ansible построен на Python и использует принцип push-модели. С вашей управляющей машины через SSH отправляются задачи прямиком на целевые серверы. Там Python-модули собираются, копируются во временную папку, исполняются и, конечно, возвращают нам результат. А самое классное? Никаких лишних агентов и никаких открытых портов! Нужен только стандартный SSH, если вы работаете с Linux, или WinRM для Windows.
| Инструмент | Модель | Агент | Язык |
|---|---|---|---|
| Ansible | Push | Нет | YAML + Jinja2 |
| Puppet | Pull | Да | DSL на Ruby |
| Chef | Pull | Да | Ruby DSL |
| SaltStack | Push/Pull | Да (minion) | YAML + Jinja2 |
Установка на управляющей машине
С чего начать? Вам понадобится рабочая станция или небольшая виртуалка с Debian/Ubuntu или AlmaLinux. На нашей практике, мы ставим её и на ноутбук, и на bastion-хост в дата-центре МТС Москва. Зачем? Чтобы можно было запускать автоматизацию из офиса или с любого другого места через bastion.
# Debian 12
apt update
apt install -y ansible ansible-lint python3-pip sshpass
pip3 install --user pywinrm pyvmomi
# AlmaLinux 9
dnf install -y epel-release
dnf install -y ansible-core ansible-collection-ansible-posix
# Проверка
ansible --version
ansible localhost -m ping
Inventory — список ваших хостов
Inventory — файл, описывающий серверы и их группы. Минимальный вариант — /etc/ansible/hosts:
[webservers]
web01.corp.example.ru
web02.corp.example.ru
web03.corp.example.ru
[dbservers]
db01.corp.example.ru
db02.corp.example.ru
[backup]
backup.corp.example.ru
[linux:children]
webservers
dbservers
backup
[windows]
dc01.corp.example.ru
dc02.corp.example.ru
[windows:vars]
ansible_connection=winrm
ansible_user=ansible@CORP.EXAMPLE.RU
ansible_winrm_transport=kerberos
ansible_winrm_server_cert_validation=ignore
На больших, разветвлённых инфраструктурах inventory удобнее хранить в YAML-формате. И наш совет: разбивайте его по отдельным папкам — так гораздо легче управлять.
inventory/
├── production/
│ ├── hosts.yml
│ ├── group_vars/
│ │ ├── all.yml
│ │ ├── webservers.yml
│ │ └── dbservers.yml
│ └── host_vars/
│ ├── web01.yml
│ └── db01.yml
└── staging/
└── hosts.yml
Первый плейбук
Что такое плейбук? Это обычный YAML-файл, где перечислены все ваши задачи. Давайте сейчас сделаем что-то простое: установим Nginx на группу серверов, которые у нас называются webservers.
# nginx-install.yml
---
- name: Базовая установка nginx
hosts: webservers
become: true
vars:
nginx_worker_processes: auto
tasks:
- name: Установка nginx
apt:
name: nginx
state: present
update_cache: true
- name: Запуск и автозагрузка
systemd:
name: nginx
state: started
enabled: true
- name: Копирование конфига
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: true
notify: reload nginx
handlers:
- name: reload nginx
systemd:
name: nginx
state: reloaded
Запуск:
ansible-playbook -i inventory/production/hosts.yml nginx-install.yml
# Dry-run перед реальным запуском
ansible-playbook -i inventory/production/hosts.yml nginx-install.yml --check --diff
# Только на одном хосте
ansible-playbook -i inventory/production/hosts.yml nginx-install.yml --limit web01
Идемпотентность — ключевое свойство
Самое классное в Ansible — это его идемпотентность. Что это значит? Можете запускать код сколько угодно раз — результат не изменится. Если пакет уже установлен, модуль apt его не трогает. Если конфиг совпадает, template ничего не перезаписывает. В выводе Ansible вы просто увидите 'changed=0' — система поняла, что менять ничего не нужно.
Я всегда запускаю свежий плейбук два раза подряд. Первый раз — changes=N, второй раз — changes=0. Если во второй раз есть изменения, значит где-то не идемпотентность: обычно это забытое creates: у команды command: или отсутствие when:.
Роли — переиспользуемые модули
А 'роль'? По сути, это просто очень удобная, стандартизированная структура каталогов.
roles/
└── nginx/
├── defaults/
│ └── main.yml
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
└── vars/
└── main.yml
Как только роль готова, плейбук пишется в одну-единственную строчку! Просто и гениально, правда?
- hosts: webservers
become: true
roles:
- nginx
- common
- monitoring
Собственные роли храним в Git, общие ставим через ansible-galaxy install.
Jinja2-шаблоны
Любой конфиг с переменными — шаблон Jinja2. Пример фрагмента nginx.conf.j2:
worker_processes {{ nginx_worker_processes | default('auto') }};
worker_connections {{ nginx_worker_connections | default(1024) }};
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.port }};
server_name {{ vhost.server_name }};
root /var/www/{{ vhost.name }};
{% if vhost.ssl | default(false) %}
ssl_certificate /etc/ssl/{{ vhost.name }}.crt;
ssl_certificate_key /etc/ssl/{{ vhost.name }}.key;
{% endif %}
}
{% endfor %}
Ansible Vault для секретов
# Шифрование файла
ansible-vault encrypt group_vars/production/secrets.yml
# Правка зашифрованного
ansible-vault edit group_vars/production/secrets.yml
# Запуск с vault-паролем
ansible-playbook site.yml --ask-vault-pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass
В CI/CD мы всегда передаём vault-password безопасно — через переменную окружения, которую получаем из Secrets Manager.
Windows через WinRM
Если работаете с Windows-машинами, есть один важный нюанс: нужно заранее настроить WinRM на целевом сервере. Мы обычно пользуемся проверенным стандартным скриптом с GitHub — тем, что лежит в репозитории ansible-windows.
# На Windows от имени администратора
Invoke-WebRequest -Uri `
"https://raw.githubusercontent.com/ansible/ansible-documentation/stable-2.16/examples/scripts/ConfigureRemotingForAnsible.ps1" `
-OutFile ConfigureRemotingForAnsible.ps1
.\ConfigureRemotingForAnsible.ps1 -CertValidityDays 3650
Простейший плейбук для Windows:
---
- hosts: windows
gather_facts: false
tasks:
- name: Создание локальной группы
ansible.windows.win_group:
name: DBAdmins
state: present
- name: Установка Chrome через Chocolatey
chocolatey.chocolatey.win_chocolatey:
name: googlechrome
state: present
Реальный кейс: накатка стандарта на 60 серверов
Вспомним один из наших кейсов: в сентябре 2024 года логистическая компания из Подольска попросила нас привести 60 Ubuntu-серверов к единому знаменателю. Это означало: одинаковый набор пакетов, пользователи, sudoers, nrpe для Nagios, rsyslog на центральный лог-сервер, одинаковые timezone, NTP, swappiness. До внедрения Ansible всё это делалось вручную при установке каждого сервера, и расхождения, конечно, набегали в стороны. Хаос, одним словом.
Собрали роль baseline на 28 задач. Плейбук запускали пачками по 10 серверов (serial: 10). Сухой прогон — 340 changes. Боевой прогон — 5 минут 40 секунд на пачку, итого 35 минут на все 60 серверов. Повторный запуск — 0 changes. С тех пор этот плейбук гоняется еженедельно из GitLab CI, любой дрейф виден в отчёте.
Бюджет этого проекта составил 95 000 рублей за настройку и готовый плейбук. А теперь самое интересное: он ежемесячно экономит клиенту около 18 часов админской работы! Сама инфраструктура, кстати, разместилась на 3 мощных серверах Dell Xeon Platinum 8280 в нашем дата-центре, с Mellanox 40G между нодами. Серьёзная связка, не так ли?
Советы из практики
- И последнее, но очень важное правило: перед любым реальным запуском на продакшене всегда, слышите, всегда прогоняйте '--check --diff'! Это ваш спасательный круг.
- Теги на задачах (
tags: nginx) — ускоряют частичный прогон. - Ещё один наш совет: всегда 'пинните' версии collections и ролей! Для этого заведите requirements.yml и прописывайте там только конкретные версии. Так вы избежите неожиданностей.
- Начинайте с `ansible-lint`. Это наш must-have! Интегрируйте его прямо в `pre-commit hook`, и он будет ловить типовые ошибки ещё до того, как вы успеете нажать "commit". Гораздо приятнее исправлять мелкие опечатки сразу, чем потом тратить время на ревью или, что хуже, на отладку уже в релизе.
- Одно важное правило, которое мы вынесли из практики: никогда не делайте больше 50 задач в одном плейбуке. Просто подумайте, кто потом будет это читать или, не дай бог, отлаживать? Разбивайте их на логичные `роли`. Это не только повышает читаемость кода, но и значительно упрощает дальнейшую поддержку и повторное использование.
- Одна ошибка может положить все ваши `prod-сервера` за секунды. Поэтому мы настоятельно советуем ограничивать `serial` на `критичных группах` серверов. Это простая, но мощная страховка: вместо того чтобы раскатывать изменения сразу на все машины, `serial` делает это постепенно. Если что-то пойдёт не так, вы потеряете лишь часть, а не весь продакшен.
Когда Ansible нужен, а когда — нет
Ansible оправдан, если:
- Пять и больше однотипных серверов, на которых регулярно выполняются одни и те же операции.
- Над инфраструктурой работает несколько инженеров и нужна согласованность конфигураций, а не «каждый по-своему».
- Серверы разворачиваются регулярно, как часть DevOps-цикла или под новые проекты.
- Нужен чёткий след — кто, когда и что именно поменял на серверах, в том числе для аудита.
Ansible можно не внедрять, если:
- Всего пара-тройка серверов, которые годами почти не меняются.
- Серверы принципиально разные по роли (БД, бэкенд, файловое хранилище, почтовый шлюз) и не образуют однотипных групп для автоматизации.
Тонкости эксплуатации на десятках серверов
- Параллельность по умолчанию — 5. На больших инвентарях (несколько десятков хостов) это заметно тормозит прогон; значение
forksв ansible.cfg стоит поднять — например, до 20, что ускоряет прогон в разы. - Логи прогонов плейбуков не сохраняются по умолчанию. Добавление callback-плагина для записи в файл позволяет потом поднять, что и когда выполнялось на каждом хосте.
- Vault-пароль не стоит держать в скрипте-обёртке в открытом виде. Практичнее переходить на vault-id с хранением пароля в keyring на управляющем узле.
FAQ — частые вопросы по Ansible
- Нужен ли Ansible, если серверов 5-10?
- Да, окупается даже на 3-5 серверах. Главное — не выигрыш во времени на одной задаче, а повторяемость и документированный процесс.
- Ansible работает с Windows?
- Да, через WinRM с HTTPS или Kerberos. Есть сотни ansible.windows модулей для PowerShell-задач.
- В чём разница между playbook и role?
- Playbook — верхнеуровневый сценарий. Role — переиспользуемый модуль с задачами, шаблонами, переменными в стандартной структуре каталогов.
- Что такое идемпотентность и зачем она?
- Многократный запуск даёт одинаковый результат. Ключевое свойство Ansible — плейбук можно запускать хоть каждый час без побочных эффектов.
- Как безопасно хранить пароли в плейбуках?
- Через ansible-vault: шифруется файл паролем или ключом. В CI/CD обычно HashiCorp Vault или AWS Secrets Manager через plugin lookup.
Источники
- Ansible Documentation: How to build your inventory — формат inventory, группы и переменные хостов.
- Ansible Documentation: Protecting sensitive data with Ansible vault — шифрование секретов через ansible-vault.
- Ansible Documentation: Windows Remote Management — подключение к Windows-хостам по WinRM.
