Аннотация
Если вы только начинаете работать с Ansible и запутались в терминах play, task и playbook, эта статья для вас.
Мы разберём, как устроен playbook, что такое Ansible tasks, чем таска отличается от модуля, и напишем небольшой плейбук “с нуля”, который устанавливает пакет, кладёт конфиг и перезапускает сервис.
В конце будет краткий чеклист “что сделать прямо сейчас” и подсказка, куда двигаться дальше.
Что такое play и task в Ansible
Представьте, что вы пишете список дел для группы серверов:
- “Установить nginx”
- “Положить конфиг”
- “Запустить службу”
В мире Ansible:
- play — это сценарий для группы хостов: “на каких серверах и под какими правами выполнять шаги”.
- task (таска) — это конкретный шаг, одна операция: установить пакет, скопировать файл, перезапустить службу.
Проще аналогия:
- play — как глава книги: “Настроить веб-серверы”.
- tasks — отдельные шаги внутри главы.
Play всегда описывается на верхнем уровне файла, а таски живут внутри него, в списке tasks:.
Чем play отличается от task
Упрощённо:
Play:
- говорит, с какими хостами работаем (hosts: web),
- под каким пользователем выполняем задачи (become: true, если нужны права администратора),
- какие переменные задаём “на всю главу”.
Task:
- делает один конкретный шаг,
- всегда вызывает один модуль с набором параметров.
Небольшой пример:
Здесь:
- - name: Настраиваем веб-серверы — это play;
- всё, что внутри tasks:, — это tasks;
- каждая таска вызывает модуль (ansible.builtin.package) с параметрами.
Простой playbook на 3–4 таски
Давайте немного усложним пример и сделаем playbook, который:
- Установит nginx.
- Скопирует файл конфигурации.
- Убедится, что nginx запущен и включён в автозагрузку.
Каждая строка - name: внутри tasks: — это отдельная таска:
- первая таска ставит пакет;
- вторая кладёт конфиг;
- третья следит, чтобы сервис был запущен и включён в автозапуск.
Модуль vs таска: в чём разница
Частый вопрос: “чем отличается модуль от таски?”
- Модуль — готовый “кирпичик кода”, который умеет делать что-то одно: ставить пакет, копировать файлы, управлять сервисом.
- Task (таска) — это конкретный вызов модуля с параметрами в вашем playbook.
Один и тот же модуль можно использовать в десятках разных тасок с разными настройками.
Примеры модулей в тасках
ansible.builtin.ping — проверить доступность хоста
Модуль ping не пингует “по сети” как утилита ping, он просто проверяет, что Ansible может подключиться к хосту и выполнить простой код.
ansible.builtin.command — выполнить произвольную команду
Модуль command запускает команду как есть. Полезно, но есть подводный камень: он обычно не знает, меняет ли команда что-то на сервере.
ansible.builtin.package / ansible.builtin.apt — поставить пакет
Или более конкретно для Debian/Ubuntu:
ansible.builtin.copy — скопировать файл
ansible.builtin.service — управлять сервисом
Итого: таска — это просто “строчка сценария”, где вы пишете: “Возьми модуль X и вызови его с такими-то параметрами”.
Идемпотентность по-человечески
Слово страшное, идея простая:
Идемпотентность — это свойство задачи, которую можно запускать много раз подряд, и результат будет предсказуемым.
Первый запуск что-то меняет, повторные — только проверяют, всё ли уже так, как нужно.
Пример неидемпотентной таски
Каждый запуск:
- команда выполняется снова,
- Ansible думает, что что-то изменилось (changed: true),
- вы не понимаете: “там реально что-то поменялось или просто команда ещё раз пробежала?”.
Пример идемпотентной таски
Что происходит:
- если nginx не установлен — модуль его поставит и покажет changed: true;
- если nginx уже есть — ничего не будет менять, changed: false.
Важно:
Старайтесь использовать специализированные модули (package, copy, service и т.д.), а не голый command/shell, когда это возможно.
Так ваши плейбуки будут безопаснее и понятнее.
Регистры (register) и debug: как заглянуть внутрь таски
Иногда нужно не просто “выполнить шаг”, а посмотреть его результат и, возможно, использовать дальше.
Для этого есть:
- ключевое слово register — сохранить результат в переменную;
- модуль ansible.builtin.debug — вывести эту переменную на экран.
Пример: сохранить результат команды
Что здесь происходит:
- первая таска выполняет uptime и кладёт полный результат в переменную uptime_result;
- вторая таска выводит на экран только текст из стандартного вывода (stdout).
В uptime_result есть много полезного:
- stdout — текстовый результат команды;
- stderr — ошибки (если были);
- rc — код возврата (0 — всё хорошо, не 0 — что-то пошло не так).
Это очень помогает при отладке: вы можете запускать плейбук, смотреть, что реально возвращает команда или модуль, и уже после этого добавлять условия и логику.
Мини-пример “с нуля”: ставим пакет, кладём конфиг, перезапускаем сервис
Соберём всё вместе в один простой пример.
Допустим, у нас есть:
- группа хостов web в инвентаре;
- файл files/app.conf рядом с плейбуком.
Напишем playbook site.yml:
Что делает этот playbook:
- Ставит nginx, если его ещё нет.
- Копирует конфиг вашего приложения.
- Запускает nginx и включает автозапуск.
- Сохраняет результат команды systemctl status в переменную.
- Показывает несколько строк статуса через debug.
Запускается это примерно так:
ansible-playbook -i inventory.ini site.yml
Где inventory.ini — ваш файл инвентаря с группой web.
Почему это работает
- Play задаёт “контекст”: с какими серверами работаем и под какими правами.
- Tasks внутри play идут сверху вниз и по очереди вызывают модули с нужными параметрами.
- Модули знают, как проверять текущее состояние (пакет установлен? файл совпадает? сервис запущен?) и принимают решение: что-то менять или нет.
- За счёт этого плейбук становится идемпотентным: его можно запускать много раз, и он будет аккуратно доводить систему до нужного состояния, а не “ломать всё по второму кругу”.
- register и debug позволяют заглянуть внутрь каждой таски и понять, что именно произошло, а не гадать по логам.
Что сделали
В этой статье мы:
- разобрали, что такое play и task в Ansible и как они связаны;
- увидели, чем таска отличается от модуля и почему “task — это вызов модуля с параметрами”;
- посмотрели на популярные модули: ping, command, package/apt, copy, service;
- по-человечески обсудили идемпотентность и почему она важна;
- научились сохранять результат таски через register и выводить его с помощью debug;
- написали простой playbook “с нуля”, который ставит пакет, кладёт конфиг и перезапускает сервис.
Сделать прямо сейчас
Небольшой чеклист:
- ✅ Найдите или создайте простой inventory с группой web.
- ✅ Создайте файл site.yml с 2–3 тасками: установка пакета, копирование файла, запуск сервиса.
- ✅ Добавьте одну таску с register + debug, чтобы потренироваться смотреть результат.
- ✅ Запустите плейбук два раза подряд и посмотрите, как меняется вывод (changed/ok).
- ✅ Попробуйте заменить command на специализированные модули там, где это возможно.
CTA
Если статья была полезной — поддержите её:
- подпишитесь на канал, чтобы не пропустить следующие части серии про Ansible (будем разбирать условия when, циклы loop и шаблоны Jinja2);
- задавайте вопросы в комментариях: можно прямо скидывать кусочки своих playbook’ов, разберём их по-человечески.