Первый playbook: структура YAML
Урок 7 - пишем первый playbook и разбираем его анатомию.
«Ad-hoc команды живут в истории терминала. Playbook живёт в git и переживёт тебя».
Playbook - это YAML-файл, описывающий желаемое состояние серверов в виде последовательности задач. Это сердце Ansible: всё серьёзное оформляется именно как playbook. Разберём минимальный пример.
---
- name: Настроить веб-серверы
hosts: web
become: true
tasks:
- name: Установить nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Запустить и включить nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
Разберём по слоям. Файл - это список плеев (play); у нас один. Плей привязывает набор задач к группе хостов: hosts: web. become: true повышает права для всего плея. tasks - список задач. Каждая задача имеет name (человекочитаемое описание) и вызов модуля с параметрами.
Запуск
ansible-playbook -i inventory.ini site.yml
# В выводе по каждой задаче и хосту будет статус:
# ok - всё уже как надо, ничего не делали
# changed - состояние изменено
# failed - ошибка
Как работает под капотом
Ansible читает YAML, строит список плеев. Для каждого плея раскрывает hosts в конкретные хосты и идёт по задачам сверху вниз. Важно: порядок выполнения - задача за задачей, но каждая задача прогоняется по всем хостам, прежде чем начнётся следующая. То есть сначала «установить nginx» на web1 и web2, потом «запустить nginx» на web1 и web2.
PLAYBOOK
+-------------------------------+
| play: hosts = web |
| task1: install nginx |
| task2: start nginx |
+-------------------------------+
|
v task1 -> [web1, web2] (по всем хостам)
v task2 -> [web1, web2] (потом следующая)
# Модель исполнения: task за task, каждый по всем хостам
hosts = ["web1", "web2"]
tasks = ["install nginx", "start nginx"]
for task in tasks:
print(f"TASK [{task}]")
for host in hosts:
print(f" ok: [{host}]")
print()
Попробуй сам ▶ Видишь, что вывод сгруппирован по задачам, а не по хостам? Именно так выглядит реальный лог ansible-playbook: блок TASK, под ним строки по каждому хосту.
Частые ошибки
- Сломанный YAML-отступ. YAML критичен к пробелам (только пробелы, не табы!). Сдвиг на пробел - и playbook не парсится.
- Забыть become. Установка пакетов без повышения прав упадёт.
- Думать, что задачи идут по хостам, а не по задачам. Ansible проходит задачи по очереди, каждую - по всем хостам.
Best practices
- Всегда давай задачам осмысленные
name- они станут логом твоей автоматизации. - Используй полные имена модулей (
ansible.builtin.apt) - это требование современных практик (FQCN). - Один плей - одна логическая роль группы хостов. Не сваливай всё в один гигантский плей.
В реальной работе
Опытные инженеры строят playbook'и по принципу «читается как инструкция для человека». Имена задач пишут так, чтобы лог выполнения сам объяснял, что происходит: не «task1», а «Установить и запустить nginx». Тогда вывод ansible-playbook становится понятным отчётом даже для того, кто не писал этот код. Ещё одна привычка - держать playbook'и тонкими: основная логика живёт в ролях, а сам site.yml лишь оркестрирует, какие роли применить к каким группам. Такой playbook на десять строк понятнее и надёжнее, чем монолит на триста, и его проще ревьюить в pull request'ах.
Итоги
Playbook - это YAML-описание задач, привязанных к группам хостов. Ansible исполняет задачи по очереди, прогоняя каждую по всем хостам. Статусы ok/changed/failed показывают результат. Дальше - подробнее про модули и идемпотентность.