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

Циклы в Ansible: loop, with_items и как не копировать таски

Аннотация Циклы в Ansible помогают не копировать одну и ту же задачу по десять раз: добавлять сразу несколько пользователей, ставить список пакетов, создавать пачку файлов. В этой статье разберём, как использовать loop, чем он отличается от старого with_items, и как писать один аккуратный таск вместо простыни копипасты. Зачем вообще циклы в Ansible Типичная боль новичка:
есть 5 пользователей — и появляется 5 одинаковых тасок, отличающихся только именем. Работает, но: тяжело поддерживать — нужно добавить ещё одного пользователя, приходится править много мест; выше риск опечатки; файл playbook раздувается и превращается в «простыню». Цикл позволяет сделать то же самое одной задачей, просто передав список значений. loop с простым списком: один таск — много объектов Начнём с самого частого случая: есть список строк (имён пользователей, пакетов, директорий). Пример: создаём нескольких пользователей Описываем список в переменной (в инвентаре или vars): Пишем одну задачу с loop: Здесь ва
Оглавление

Аннотация

Циклы в Ansible помогают не копировать одну и ту же задачу по десять раз: добавлять сразу несколько пользователей, ставить список пакетов, создавать пачку файлов. В этой статье разберём, как использовать loop, чем он отличается от старого with_items, и как писать один аккуратный таск вместо простыни копипасты.

Зачем вообще циклы в Ansible

Типичная боль новичка:

есть 5 пользователей — и появляется 5 одинаковых тасок, отличающихся только именем.

-2

Работает, но:

  • тяжело поддерживать — нужно добавить ещё одного пользователя, приходится править много мест;
  • выше риск опечатки;
  • файл playbook раздувается и превращается в «простыню».

Цикл позволяет сделать то же самое одной задачей, просто передав список значений.

loop с простым списком: один таск — много объектов

Начнём с самого частого случая: есть список строк (имён пользователей, пакетов, директорий).

Пример: создаём нескольких пользователей

  • Описываем список в переменной (в инвентаре или vars):
-3
  • Пишем одну задачу с loop:
-4

Здесь важно:

  • loop перебирает список по одному элементу;
  • внутри таски текущий элемент доступен как переменная item;
  • в нашем случае item — это просто строка: alice, bob, carol.

Типичная ошибка:

забыть кавычки вокруг {{ users_to_create }} в loop.

Правильно: loop: "{{ users_to_create }}", иначе Ansible может воспринять это как текст, а не как переменную.

Пример: ставим несколько пакетов

-5

Один таск — сколько угодно пакетов.

loop со словарями: item.name, item.uid и другие поля

Иногда одной строки недостаточно. Например, для пользователя хочется задать:

  • имя,
  • uid,
  • shell.

Тогда удобно использовать список словарей (в YAML это «список объектов»).

Описываем данные

-6

Здесь каждый элемент списка — это словарь с полями name, uid, shell.

Используем в таске

-7

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

  • на первой итерации item = {name: alice, uid: 1010, shell: /bin/bash};
  • вы обращаетесь к полям как item.name, item.uid, item.shell;
  • на второй итерации — то же самое, но для bob.

Важно: если в словаре нет нужного ключа (например, забыли указать shell), Ansible упадёт с ошибкой.

Чтобы подстраховаться, иногда используют default:

-8

Тогда, если в каком-то элементе нет shell, Ansible подставит /bin/bash.

Коротко: with_items vs loop — что выбирать новичку

Исторически в Ansible сначала появился with_items, а loop добавили позже как более единый и понятный механизм.

Старый вариант:

-9

Новый (рекомендуемый) вариант:

-10

Для новичка важно запомнить простое правило:

Сейчас смотреть в сторону loop.

with_items оставили для совместимости со старыми плейбуками, но новые примеры и документация опираются на loop.

Плюсы loop:

  • один синтаксис для всех циклов (loop, loop_control и т.д.);
  • проще читать новые примеры;
  • меньше «магии» с разными with_*.

Подводные камни и небольшие подсказки

1. Имена переменных

Не используйте item вне цикла — можно запутаться. Лучше выносить исходные данные в переменные вроде users_to_create, packages_common и т.п.

2. Ошибки отступов

YAML очень чувствителен к отступам. Если loop: уехал правее/левее, чем нужно — таска может вести себя странно или не запуститься.

3. Сообщение (name) и цикл

Чтобы видеть в выводе, с кем сейчас работает таска, можно вывести item в названии:

-11

Тогда в выводе будет понятно, на ком именно таска «споткнулась», если что-то пошло не так.

Почему это работает

Ansible выполняет playbook пошагово, а loop превращает одну задачу в несколько запусков одного и того же модуля с разными данными.

Вместо того чтобы вы копировали таску, Ansible сам «прокручивает» список:

  • берёт первый элемент — запускает модуль,
  • берёт второй элемент — запускает тот же модуль ещё раз,
  • и так далее.

Благодаря этому:

  • плейбук короче и понятнее;
  • проще менять набор данных (добавили элемент в список — цикл сам его обработает);
  • меньше копипаста — значит, меньше вероятность опечаток и расхождений.

Что сделали

В этой статье мы:

  • разобрали, зачем вообще нужны циклы в Ansible;
  • увидели, как использовать loop с простым списком строк;
  • посмотрели, как работать с списком словарей через item.name, item.uid и другие поля;
  • коротко сравнили with_items и loop, и решили, что новичку хватит loop;
  • разобрали пару типичных ошибок и подсказок по оформлению.

Сделать прямо сейчас

Небольшой чеклист, который можно применить сразу:

  • Найдите в своём плейбуке место, где вы копируете похожие таски — попробуйте заменить их на одну задачу с loop.
  • Вынесите «сырые данные» в переменные (users_to_create, packages_common), чтобы плейбук было легче читать.
  • Попробуйте создать список словарей и использовать item.name, item.uid в одной из задач.
  • Добавьте имя текущего элемента в name таски, чтобы вывод был нагляднее.
  • Сохраните себе шаблон простого цикла, чтобы использовать его как заготовку в новых проектах.

CTA

Если эта статья помогла приручить циклы в Ansible и избавиться от копипасты в плейбуках — подпишитесь на серию материалов про Ansible простым языком.

Пишите в комментариях, какие темы по Ansible болят больше всего — разберём их в следующих выпусках.