Циклы (loop, with_items)

Тема дорожной карты · Ansible

Циклы в Ansible являются мощным инструментом для автоматизации задач, которые нужно повторять для множества элементов. Они позволяют упростить и уменьшить количество кода, необходимого для выполнения однотипных операций, таких как установка пакетов или копирование файлов. Вместо того чтобы дублировать определения задач для каждого элемента, можно использовать циклы для выполнения одной и той же задачи для всех элементов в списке. Это делает Ansible более эффективным и удобным для управления большим количеством ресурсов.

Современное ключевое слово для циклов — loop, которое принимает список напрямую: например, loop: "{{ packages }}" в сочетании с ansible.builtin.package: name: "{{ item }}" устанавливает каждый пакет из списка в одном блоке задачи. Устаревшие конструкции, такие как with_items, with_dict и другие with_*, по-прежнему поддерживаются, но объявлены устаревшими в пользу loop с фильтрами Jinja2, такими как dict2items. Для вложенных итераций Ansible предоставляет loop с фильтром subelements, а переменные цикла вроде loop.index и loop.last дают доступ к метаданным итерации внутри задачи.

Как это работает

Циклы (loop, with_items) — это стандартная единица в Ansible: YAML-файл со списком play; у каждого play — hosts, tasks, опционально pre_tasks/post_tasks/handlers/vars/roles. Задачи выполняются последовательно для каждого хоста; handlers — в конце play, только при триггере (notify). Strategy управляет параллелизмом: linear (дефолт — ждёт медленный), free (каждый хост так быстро, как может). Tags позволяют запускать подмножества (--tags backup); --start-at-task возобновляет после сбоя.

Циклы в Ansible позволяют повторно использовать одну и ту же задачу для множества элементов. Это достигается с помощью ключевого слова loop, которое принимает список элементов напрямую. Например, loop: "{{ packages }}" позволяет установить каждый пакет из списка packages в одном блоке задачи. Устаревшие конструкции, такие как with_items, with_dict и другие with_*, по-прежнему поддерживаются, но они объявлены устаревшими в пользу loop с фильтрами Jinja2, такими как dict2items. Для вложенных итераций Ansible предоставляет loop с фильтром subelements, а переменные цикла, такие как loop.index и loop.last, дают доступ к метаданным итерации внутри задачи.

Когда применять

Всегда оборачивайте связанные операции в плейбук — даже если начинаете с одной задачи, растёт. pre_tasks — для setup, который должен идти первым; handlers — для идиомы "перезапустить X, если конфиг изменился"; tags — для частичных запусков. serial: 1 или serial: 25% — для постепенной выкатки (canary). Тестируйте --check --diff в CI против staging-inventory.

Циклы (loop, with_items) полезны в ситуациях, где вам нужно выполнить одну и ту же операцию для множества элементов. Например, установка множества пакетов, копирование файлов на множество хостов или выполнение одной и той же команды для множества пользователей. pre_tasks — это удобный способ выполнить подготовительные задачи, которые должны выполняться перед основной задачей. handlers позволяют автоматически перезапустить сервис, если его конфигурация была изменена. tags позволяют запускать подмножество задач без необходимости запускать весь плейбук. serial позволяет постепенно выкатывать изменения, что полезно для минимизации риска сбоя в продакшне.

Типичные ошибки

Ловушки Циклы (loop, with_items): длинные плейбуки без tags (нужно гонять всё для теста одной секции); ignore_errors: true повсюду (тихие сбои); нет block + rescue + always для error handling; баги отступов YAML (используйте линтер — ansible-lint); become: true на уровне play, когда нужен root только для одной задачи.

Связанные понятия

Полезные ресурсы

Проверить знания (1)

Загрузка вопросов…