Найти в Дзене
Infra as Code по-русски

Ansible tasks и playbook: простыми словами

Аннотация Если вы только начинаете работать с Ansible и запутались в терминах play, task и playbook, эта статья для вас.
Мы разберём, как устроен playbook, что такое Ansible tasks, чем таска отличается от модуля, и напишем небольшой плейбук “с нуля”, который устанавливает пакет, кладёт конфиг и перезапускает сервис. В конце будет краткий чеклист “что сделать прямо сейчас” и подсказка, куда двигаться дальше. Представьте, что вы пишете список дел для группы серверов: В мире Ansible: Проще аналогия: Play всегда описывается на верхнем уровне файла, а таски живут внутри него, в списке tasks:. Упрощённо: Play: Task: Небольшой пример: Здесь: Давайте немного усложним пример и сделаем playbook, который: Каждая строка - name: внутри tasks: — это отдельная таска: Частый вопрос: “чем отличается модуль от таски?” Один и тот же модуль можно использовать в десятках разных тасок с разными настройками. ansible.builtin.ping — проверить доступность хоста Модуль ping не пингует “по сети” как утилита pin
Оглавление

Аннотация

Если вы только начинаете работать с 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:

  • делает один конкретный шаг,
  • всегда вызывает один модуль с набором параметров.

Небольшой пример:

-2

Здесь:

  • - name: Настраиваем веб-серверы — это play;
  • всё, что внутри tasks:, — это tasks;
  • каждая таска вызывает модуль (ansible.builtin.package) с параметрами.

Простой playbook на 3–4 таски

Давайте немного усложним пример и сделаем playbook, который:

  1. Установит nginx.
  2. Скопирует файл конфигурации.
  3. Убедится, что nginx запущен и включён в автозагрузку.
-3

Каждая строка - name: внутри tasks: — это отдельная таска:

  • первая таска ставит пакет;
  • вторая кладёт конфиг;
  • третья следит, чтобы сервис был запущен и включён в автозапуск.

Модуль vs таска: в чём разница

Частый вопрос: “чем отличается модуль от таски?”

  • Модуль — готовый “кирпичик кода”, который умеет делать что-то одно: ставить пакет, копировать файлы, управлять сервисом.
  • Task (таска) — это конкретный вызов модуля с параметрами в вашем playbook.

Один и тот же модуль можно использовать в десятках разных тасок с разными настройками.

Примеры модулей в тасках

ansible.builtin.ping — проверить доступность хоста

-4

Модуль ping не пингует “по сети” как утилита ping, он просто проверяет, что Ansible может подключиться к хосту и выполнить простой код.

ansible.builtin.command — выполнить произвольную команду

-5

Модуль command запускает команду как есть. Полезно, но есть подводный камень: он обычно не знает, меняет ли команда что-то на сервере.

ansible.builtin.package / ansible.builtin.apt — поставить пакет

-6

Или более конкретно для Debian/Ubuntu:

-7

ansible.builtin.copy — скопировать файл

-8

ansible.builtin.service — управлять сервисом

-9

Итого: таска — это просто “строчка сценария”, где вы пишете: “Возьми модуль X и вызови его с такими-то параметрами”.

Идемпотентность по-человечески

Слово страшное, идея простая:

Идемпотентность — это свойство задачи, которую можно запускать много раз подряд, и результат будет предсказуемым.

Первый запуск что-то меняет, повторные — только проверяют, всё ли уже так, как нужно.

Пример неидемпотентной таски

-10

Каждый запуск:

  • команда выполняется снова,
  • Ansible думает, что что-то изменилось (changed: true),
  • вы не понимаете: “там реально что-то поменялось или просто команда ещё раз пробежала?”.

Пример идемпотентной таски

-11

Что происходит:

  • если nginx не установлен — модуль его поставит и покажет changed: true;
  • если nginx уже есть — ничего не будет менять, changed: false.

Важно:

Старайтесь использовать
специализированные модули (package, copy, service и т.д.), а не голый command/shell, когда это возможно.

Так ваши плейбуки будут безопаснее и понятнее.

Регистры (register) и debug: как заглянуть внутрь таски

Иногда нужно не просто “выполнить шаг”, а посмотреть его результат и, возможно, использовать дальше.

Для этого есть:

  • ключевое слово register — сохранить результат в переменную;
  • модуль ansible.builtin.debug — вывести эту переменную на экран.

Пример: сохранить результат команды

-12

Что здесь происходит:

  • первая таска выполняет uptime и кладёт полный результат в переменную uptime_result;
  • вторая таска выводит на экран только текст из стандартного вывода (stdout).

В uptime_result есть много полезного:

  • stdout — текстовый результат команды;
  • stderr — ошибки (если были);
  • rc — код возврата (0 — всё хорошо, не 0 — что-то пошло не так).

Это очень помогает при отладке: вы можете запускать плейбук, смотреть, что реально возвращает команда или модуль, и уже после этого добавлять условия и логику.

Мини-пример “с нуля”: ставим пакет, кладём конфиг, перезапускаем сервис

Соберём всё вместе в один простой пример.

Допустим, у нас есть:

  • группа хостов web в инвентаре;
  • файл files/app.conf рядом с плейбуком.

Напишем playbook site.yml:

-13

Что делает этот playbook:

  1. Ставит nginx, если его ещё нет.
  2. Копирует конфиг вашего приложения.
  3. Запускает nginx и включает автозапуск.
  4. Сохраняет результат команды systemctl status в переменную.
  5. Показывает несколько строк статуса через 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’ов, разберём их по-человечески.