Роли Ansible и Ansible Galaxy: переиспользование

Рейтинг: 71.7% · 16 голосов
Подробный курс по Ansible с прицелом на экзамен RHCE EX294: установка и инвентарь, плейбуки, переменные и факты, Vault, циклы и условия, шаблоны Jinja2, роли и коллекции, Execution Environments и ansible-navigator, управление системами (диски, LVM, cron, SELinux, firewalld). Примеры на RHEL/Fedora. Актуально на 2026.
Ответить
Аватара пользователя
Maksim_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Роли Ansible и Ansible Galaxy: переиспользование

Сообщение Maksim_DevOps »

Оглавление курса (47)
  1. Что такое Ansible и зачем он нужен: автоматизация без агентов
  2. Сертификация RHCE и экзамен EX294: что внутри и как готовиться
  3. Архитектура Ansible: control node, узлы, модули и плагины
  4. Установка Ansible на control node: dnf, pip и версии ansible-core
  5. Подготовка управляемых узлов: SSH, пользователь и sudo
  6. Инвентарь Ansible: hosts, группы и переменные
  7. Настройка Ansible: файл ansible.cfg и приоритеты конфигурации
  8. Host patterns и инструменты командной строки Ansible
  9. Ad hoc команды Ansible: быстрые задачи без плейбука
  10. Ansible playbook: что это такое и как устроен
  11. Структура плейбука: play, task, модули и переменные
  12. Запуск плейбуков: проверка, теги, ограничения и отладка
  13. Параллелизм и порядок выполнения: forks, serial, strategy
  14. Факты Ansible: сбор информации об узлах
  15. Переменные Ansible: типы, объявление и приоритет
  16. Регистрация результатов и специальные переменные
  17. Ansible Vault: шифрование паролей и секретов
  18. Организация инвентаря: group_vars, host_vars и вложенные группы
  19. Динамический инвентарь и инвентарные плагины
  20. Циклы в Ansible: loop, списки и словари
  21. Повтор задачи до условия: until, retries и delay
  22. Условия в Ansible: директива when и логика
  23. Jinja2 в Ansible: выражения, фильтры и подстановки
  24. Обработчики Ansible: handlers, notify и flush_handlers
  25. Обработка ошибок: failed_when, changed_when и ignore_errors
  26. Блоки в Ansible: block, rescue и always
  27. Управление файлами: модули file, copy, fetch и stat
  28. Архивы и сборка файлов: archive, unarchive, assemble
  29. Точечное редактирование файлов: lineinfile и blockinfile
  30. Шаблоны Jinja2: модуль template и динамические конфиги
  31. Jinja2 продвинуто: фильтры, циклы, макросы и lookup
  32. Модули Ansible: ansible-doc и поиск нужного модуля
  33. Разработка собственного модуля Ansible на Python
  34. Роли Ansible и Ansible Galaxy: переиспользование (вы здесь)
  35. Разработка роли Ansible: создание с нуля
  36. Зависимости ролей и requirements.yml
  37. Коллекции Ansible: ansible.posix, community и своя коллекция
  38. Execution Environments: контейнеры для запуска Ansible
  39. Сборка Execution Environment с ansible-builder
  40. ansible-navigator: запуск плейбуков в Execution Environment
  41. Управление SSH-ключами через Ansible: authorized_key
  42. Управление дисками: filesystem, mount и parted
  43. LVM через Ansible: тома, группы и расширение
  44. Планировщик задач: cron и systemd timers через Ansible
  45. Безопасность: hardening SSH и репозитории dnf/yum
  46. SELinux через Ansible: булевы, контексты и порты
  47. Сквозной проект и подготовка к экзамену EX294
Представь плейбук, который сначала был на двадцать строк, а через полгода распух до восьмисот. Установка пакетов, шаблоны конфигов, хендлеры, переменные окружения, проверки firewalld - все свалено в один файл. Поправить что-то страшно, переиспользовать на другом проекте невозможно: только копипастить куски и молиться. Знакомо? Это та самая боль, ради которой придумали роли.

Что такое роли Ansible и зачем они нужны

Роль (role) - это способ разложить плейбук по полочкам. Вместо одного гигантского файла ты получаешь стандартный набор каталогов, где у каждого типа сущностей свое место: задачи отдельно, хендлеры отдельно, шаблоны отдельно. Ansible сам знает, где что искать, поэтому тебе не нужно прописывать пути руками.

Главных причин использовать роли две. Первая - переиспользование: настроил один раз роль nginx, и подключаешь ее в десятке проектов одной строкой. Вторая - порядок и читаемость: когда ansible roles разбиты по структуре, в чужом (и своем полугодовалом) коде разбираешься за минуты, а не за день. На экзамене EX294 роли - это крупный блок, и спрашивают там именно умение создать роль с нуля и грамотно ее применить, а не пересказ теории.

Создать каркас роли проще всего командой:

Код: Выделить всё

ansible-galaxy role init webserver
Она разложит стандартное дерево. Вот как выглядят роли ansible изнутри:

Код: Выделить всё

roles/
└── webserver/
    ├── tasks/
    │   └── main.yml      # точка входа: основные задачи
    ├── handlers/
    │   └── main.yml      # обработчики (notify их дергает)
    ├── templates/
    │   └── nginx.conf.j2 # Jinja2-шаблоны для template
    ├── files/
    │   └── index.html    # статические файлы для copy
    ├── vars/
    │   └── main.yml      # переменные с высоким приоритетом
    ├── defaults/
    │   └── main.yml      # переменные по умолчанию (низкий приоритет)
    ├── meta/
    │   └── main.yml      # метаданные и зависимости роли
    └── README.md
Ключевой момент: файл tasks/main.yml - это точка входа роли. Когда роль подключается, Ansible выполняет именно его. Внутри ты обращаешься к файлам и шаблонам по короткому имени: модуль ansible.builtin.template с параметром src: nginx.conf.j2 сам найдет файл в templates/ этой роли, а ansible.builtin.copy с src: index.html - в files/. Полные пути писать не надо, в этом и магия.

Разница между defaults/ и vars/ важна на практике. В defaults кладут значения, которые пользователь роли спокойно переопределит (порт, имя сайта) - у них самый низкий приоритет. В vars держат то, что менять не стоит, у них приоритет высокий. Если хочешь, чтобы роль легко настраивалась снаружи, выноси параметры в defaults.

Изображение

Ansible Galaxy: где брать готовые роли

Не все нужно писать самому. Ansible Galaxy - это публичный репозиторий ролей и коллекций, своего рода npm для Ansible. Тысячи готовых ролей: настройка PostgreSQL, Docker, Nginx, мониторинга. Прежде чем писать роль docker руками, загляни туда - наверняка уже есть отлаженный вариант.

Установка одной роли делается так:

Код: Выделить всё

ansible-galaxy role install geerlingguy.nginx
ansible-galaxy role list
По умолчанию роль скачается в ~/.ansible/roles/. Имя в формате namespace.role - это автор и название. Команда ansible galaxy install подтянет архив и распакует его готовым к использованию.

Но в реальных проектах роли не ставят по одной руками. Описывают их списком в файле requirements.yml и кладут его в репозиторий проекта. Тогда любой коллега одной командой развернет тот же набор зависимостей:

Код: Выделить всё

# requirements.yml
roles:
  - name: geerlingguy.nginx
    version: "3.1.4"

  - name: my_app
    src: https://github.com/myorg/ansible-role-app.git
    scm: git
    version: main

collections:
  - name: ansible.posix
  - name: community.general
Атрибут src обязателен, если ставишь не из Galaxy, а из своего git-репозитория. version фиксирует тег или ветку - всегда указывай его явно, иначе завтра в роль прилетит ломающее обновление, и плейбук развалится без единой правки с твоей стороны. Ставим все разом:

Код: Выделить всё

ansible-galaxy install -r requirements.yml -p roles/
Флаг -p roles/ кладет роли прямо в каталог проекта рядом с плейбуком. Это удобно, когда команда работает в одном репозитории. Для коллекций используется ansible-galaxy collection install -r requirements.yml.

Подключение роли: roles vs include_role и порядок выполнения

Способ первый, классический - секция roles: в плее. Это статическое подключение: Ansible читает роли на этапе разбора плейбука, до старта выполнения.

Код: Выделить всё

- name: Настройка веб-сервера
  hosts: web
  become: true
  roles:
    - webserver
    - geerlingguy.nginx
Способ второй - модули include_role и import_role внутри блока tasks. Они дают больше контроля: роль можно вызвать по условию, в цикле или передать ей параметры прямо в месте вызова.

Код: Выделить всё

  tasks:
    - name: Базовая роль всегда
      ansible.builtin.import_role:
        name: common

    - name: А эту - только для прода
      ansible.builtin.include_role:
        name: monitoring
      when: env == "prod"
Теперь о разнице, на которой многие путаются. import_role - статический: роль разворачивается на этапе парсинга, как и секция roles:. Все ее задачи видны в ansible-playbook --list-tasks, теги на них работают корректно, поведение предсказуемое. include_role - динамический: роль подключается в момент выполнения. Только так работают цикл loop по ролям и подстановка имени роли через переменную. Платой за гибкость идет то, что теги на отдельные задачи внутри роли применить уже нельзя - тег навешивается на сам include. Правило простое: по умолчанию бери import (или секцию roles:), переходи на include только когда нужны цикл или условие, влияющее на сам факт подключения.

Отдельно разберем порядок выполнения - это любят на экзамене. Внутри одного плея этапы идут строго так: сначала pre_tasks, затем хендлеры из pre_tasks, потом roles (роли из секции roles:), за ними обычные tasks, и в конце post_tasks. Хендлеры запускаются после каждого блока, если их кто-то notify-нул.

Код: Выделить всё

- hosts: web
  become: true
  pre_tasks:
    - name: Обновить кеш пакетов
      ansible.builtin.dnf:
        update_cache: true
  roles:
    - webserver
  tasks:
    - name: Открыть порт в firewalld
      ansible.posix.firewalld:
        service: http
        permanent: true
        state: enabled
        immediate: true
  post_tasks:
    - name: Дернуть healthcheck
      ansible.builtin.uri:
        url: http://localhost/health
        status_code: 200
Запомни последовательность как мантру: pre_tasks - roles - tasks - post_tasks. Если задача из роли почему-то выполняется не тогда, когда ты ждал, первым делом проверь, в каком из этих блоков она сидит.

Небольшая ремарка про дистрибутивы. Все примеры заточены под RHEL/Fedora: dnf, systemd, firewalld, SELinux. Готовые роли из Galaxy обычно умеют определять ОС и сами выбирают между dnf и apt - например geerlingguy.nginx работает и на RHEL, и на Ubuntu/Debian. На RU-системах (RED OS, Astra) роли тоже едут, но загляни в их defaults/main.yml: иногда имя пакета или сервиса отличается, и его надо переопределить.

Типичные грабли
  • Забыл version в requirements.yml - и однажды роль обновилась, переменные переименовались, плейбук упал. Пинуй версии всегда.
  • Положил переменную в vars/ вместо defaults/ и удивляешься, почему ее не получается переопределить снаружи. Высокий приоритет vars перебивает почти все.
  • Ждешь, что include_role с when выполнится статически, а он динамический - и тег на внутренние задачи не сработал. Для тегов нужен import_role.
  • Путаешь приоритет блоков: думал, что tasks идут перед ролями. Нет, roles раньше tasks. Из-за этого порт в firewalld открывался до того, как роль успевала поставить сервис.
  • Поставил роль без -p roles/, она легла в ~/.ansible/roles/, а коллега ее не видит, потому что у него этого каталога нет. Держи зависимости в проекте.
Мини-лаба
  • Создай роль командой ansible-galaxy role init webserver и изучи дерево каталогов.
  • В tasks/main.yml роли поставь nginx через dnf, развесь конфиг шаблоном template из templates/, добавь хендлер перезапуска сервиса.
  • Вынеси порт и имя сайта в defaults/main.yml, подключи роль через секцию roles: и переопредели порт в плейбуке.
  • Опиши в requirements.yml роль geerlingguy.nginx с пином версии и установи ее командой ansible-galaxy install -r requirements.yml -p roles/.
  • Добавь в плей pre_tasks (обновление кеша), post_tasks (проверка через uri) и убедись по выводу, что порядок именно pre - roles - tasks - post.
Контрольные вопросы
  • Чем отличается каталог defaults/ от vars/ внутри роли и где хранить переопределяемые параметры?
  • В чем разница между import_role и include_role, и когда обязателен именно динамический include?
  • В каком порядке выполняются pre_tasks, roles, tasks и post_tasks в одном плее?
  • Зачем нужен requirements.yml и что делает флаг -p в команде ansible-galaxy install?
Итог

Роли превращают хаос из одного длинного плейбука в переиспользуемые блоки со стандартной структурой каталогов. Готовое тащи из Ansible Galaxy через requirements.yml с пином версий, подключай через roles: или import_role для предсказуемости, а include_role доставай, когда нужны цикл или условие. И держи в голове порядок pre_tasks - roles - tasks - post_tasks: на EX294 этот вопрос всплывает регулярно, а в реальной отладке экономит часы.
👍2 ❤️ 🔥1 😄 🤔1
Аватара пользователя
grumpynullptr
Сообщения: 1
Зарегистрирован: 14 май 2026, 02:29

Re: Роли Ansible и Ansible Galaxy: переиспользование

Сообщение grumpynullptr »

Наконец-то дошло про порядок. У меня firewalld открывал порт раньше чем роль ставила nginx, и я полдня не мог понять почему хелсчек падает. Оказалось tasks идут после roles, спасибо.
👍 ❤️ 🔥2 😄 🤔
Аватара пользователя
ladkins
Сообщения: 1
Зарегистрирован: 19 май 2026, 21:12

Re: Роли Ansible и Ansible Galaxy: переиспользование

Сообщение ladkins »

А можно подробнее почему include_role с тегами не дружит? У меня в CI тег ставится на роль через include и не подхватывает внутренние задачи, теперь понятно что надо import_role. Полезный урок.
👍1 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Разработка собственного модуля Ansible на Python
Следующая глава →
Разработка роли Ansible: создание с нуля

Все главы курса «Ansible: автоматизация и подготовка к RHCE (EX294)»

Поделиться темой: ✈ Telegram VK
Похожие запросы: что такое ansible простыми словамиansible для начинающих с чего начатьустановка ansible на linuxansible inventory и hosts файлчто такое playbook в ansibleструктура ansible playbook из чего состоит

Вернуться в «Ansible: автоматизация и подготовка к RHCE (EX294)»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость