← Назад к вопросам

Что такое циклы в Ansible playbook?

1.7 Middle🔥 161 комментариев
#Ansible и управление конфигурацией

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Циклы в Ansible Playbook: Механизм Повторяющихся Задач

В контексте Ansible, циклы (loops) — это механизм, позволяющий выполнять одну задачу (task) или модуль (module) многократно для разных элементов данных, таких как список значений, список словарей или даже результаты предыдущих команд. Это фундаментальная концепция, заменяющая классические итеративные конструкции из языков программирования (как for или while) и обеспечивающая декларативность и идемпотентность, которые являются краеугольными камнями философии Ansible.

Основная цель циклов — устранение дублирования кода. Без них пришлось бы писать отдельную задачу для каждого конфигурируемого пользователя, устанавливаемого пакета или изменяемого файла, что привело бы к огромным, трудночитаемым playbook.

Ключевые Типы Циклов в Ansible

Ansible эволюционировал, и сегодня существует несколько способов организации циклов:

  1. Классический цикл loop (рекомендуемый с Ansible 2.5+): Современный и наиболее гибкий вариант.
  2. Устаревшие циклы with_<lookup> (например, with_items): Использовались до версии 2.5. Хотя они до сих пор поддерживаются, документация рекомендует переход на loop.
  3. Цикл until: Позволяет повторять задачу до тех пор, пока не будет выполнено определённое условие (например, успешный выход команды). Это аналог цикла while.

Практические Примеры Использования Цикла loop

Пример 1: Работа с простым списком (list)

Самый частый сценарий — установка нескольких пакетов одной задачей.

- name: Install a list of packages
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - postgresql
    - redis-server

В этом примере задача выполнится трижды. В каждой итерации переменная item будет принимать следующее значение из списка (nginx, затем postgresql, затем redis-server).

Пример 2: Работа со списком словарей (list of dictionaries)

Часто параметры задачи требуют более одной переменной на элемент. Здесь на помощь приходят словари.

- name: Create multiple users with additional properties
  ansible.builtin.user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
    shell: "{{ item.shell | default('/bin/bash') }}"
  loop:
    - { name: 'alice', groups: 'sudo,dev', shell: '/bin/zsh' }
    - { name: 'bob', groups: 'dev' }
    - { name: 'charlie', groups: 'admin' }

Здесь item в каждой итерации — это целый словарь. Мы обращаемся к его ключам (item.name, item.groups).

Пример 3: Использование зарегистрированных переменных (register) в цикле

Можно сохранить результат каждой итерации цикла для последующего анализа.

- name: Check connectivity to a set of ports
  ansible.builtin.wait_for:
    host: "{{ inventory_hostname }}"
    port: "{{ item }}"
    timeout: 5
  loop: [ 80, 443, 22, 3306 ]
  register: port_check_result
  ignore_errors: yes

- name: Report which ports are open
  ansible.builtin.debug:
    msg: "Port {{ item.item }} is {{ 'OPEN' if item.success else 'CLOSED/UNREACHABLE' }}"
  loop: "{{ port_check_result.results }}"

Ключевой момент: при использовании register внутри цикла, результатом будет не один объект, а список results, где каждый элемент соответствует одной итерации и содержит стандартные ключи (item, success, stdout и т.д.).

Важные Особенности и Best Practices

  • Читаемость: Циклы loop делают код более понятным по сравнению с with_items.
  • Управление ошибками: Параметр ignore_errors: yes позволяет циклу продолжиться даже при сбое в одной из итераций. Более тонкое управление обеспечивает failed_when.
  • Фильтрация и преобразования: Перед передачей в цикл данные можно обработать с помощью Jinja2 фильтров. Например, loop: "{{ list_of_hosts | unique }}" для исключения дубликатов.
  • Вложенные циклы: Для создания комбинаций элементов (декартово произведение) можно использовать фильтр Jinja2 product.
- name: Create directories for multiple apps and environments
  ansible.builtin.file:
    path: "/data/{{ item[0] }}/{{ item[1] }}"
    state: directory
  loop: "{{ ['app1', 'app2'] | product(['prod', 'stage', 'dev']) | list }}"
# Создаст: /data/app1/prod, /data/app1/stage, ... /data/app2/dev

Итог: Циклы в Ansible — это мощный и элегантный инструмент для соблюдения принципа DRY (Don't Repeat Yourself). Они позволяют писать компактные, легко поддерживаемые и масштабируемые playbook, эффективно управляя конфигурацией множества однотипных объектов. Переход на современный синтаксис loop — признак хорошо структурированного и готового к будущим обновлениям проекта.

Что такое циклы в Ansible playbook? | PrepBro