Шаблоны Jinja2: модуль template и динамические конфиги

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

Шаблоны Jinja2: модуль template и динамические конфиги

Сообщение 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
Представь задачу: один и тот же nginx нужно раскатить на десяток узлов, но в dev слушать 8080 и логировать в debug, в prod - 80/443 и warn, а число воркеров на каждой машине своё, по числу ядер. Если ты будешь руками править конфиг под каждый хост или городить десять почти одинаковых файлов в репозитории - ты утонешь. Ровно эту боль и снимают шаблоны Jinja2 и модуль template: пишешь ОДИН конфиг с дырками под переменные, а Ansible на каждом узле подставляет нужные значения и факты и кладёт готовый файл.

Это одна из самых рабочих и самых экзаменуемых тем. Если коротко: ansible template - это про то, как из единственного .j2-файла получить N разных, но корректных конфигов. Поехали разбираться, как это устроено.

Чем template отличается от copy и зачем тут jinja2 шаблоны

Модуль ansible.builtin.copy кладёт файл на узел КАК ЕСТЬ, байт в байт. Никакой обработки содержимого - что в исходнике, то и на сервере. Это идеально для бинарников, ключей, статики.

Модуль ansible.builtin.template работает иначе: он берёт исходный файл (по соглашению с расширением .j2), прогоняет его через движок шаблонов Jinja2, подставляет переменные, факты, выполняет циклы и условия - и только результат кладёт на целевой хост. То есть template = copy + рендеринг.

Внутри .j2-файла действуют три конструкции Jinja2, которые надо запомнить намертво:
  • {{ ... }} - выражение, подставить значение. Например {{ http_port }} превратится в 80.
  • {% ... %} - управляющая логика: циклы for, условия if, set.
  • {# ... #} - комментарий, в итоговый файл НЕ попадёт.
Где template ищет .j2? Если ты вызываешь его из роли, путь src указывается относительно каталога templates/ этой роли - искать ничего вручную не надо. В обычном плейбуке - относительно каталога с плейбуком. Это частая засада на старте: положил шаблон не туда и ловишь "Could not find or access".

Изображение

Переменные, факты, циклы и условия внутри шаблона

В jinja2 шаблоны попадает ВЕСЬ контекст переменных Ansible, который виден задаче: vars, group_vars, host_vars, defaults роли, а также собранные факты (ansible_facts). Это и есть суперсила: конфиг подстраивается под конкретную машину сам.

Простой пример - кусок шаблона nginx.conf.j2:

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

# {{ ansible_managed }}
user  nginx;
worker_processes  {{ ansible_facts['processor_vcpus'] }};

events {
    worker_connections  {{ nginx_worker_connections | default(1024) }};
}

http {
    server {
        listen {{ http_port }};
        server_name {{ ansible_facts['fqdn'] }};
{% if enable_tls %}
        listen 443 ssl;
        ssl_certificate     /etc/pki/tls/certs/{{ cert_name }}.crt;
        ssl_certificate_key /etc/pki/tls/private/{{ cert_name }}.key;
{% endif %}

{% for backend in upstreams %}
        location {{ backend.path }} {
            proxy_pass http://{{ backend.host }}:{{ backend.port }};
        }
{% endfor %}
    }
}
Разбор по строчкам. worker_processes берётся из факта - сколько vCPU на узле, столько и воркеров, без ручной настройки. Фильтр default(1024) подставит 1024, если переменная nginx_worker_connections не задана - это страховка от undefined. Блок {% if enable_tls %} целиком включается или выпадает в зависимости от булевой переменной. Цикл {% for backend in upstreams %} разворачивает список словарей в набор location-блоков.

А вот переменные, которые этот шаблон ждёт, например в group_vars/prod.yml:

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

http_port: 80
enable_tls: true
cert_name: cyberlake
nginx_worker_connections: 4096
upstreams:
  - path: /
    host: 10.0.0.10
    port: 8080
  - path: /api
    host: 10.0.0.11
    port: 9000
Для dev делаешь group_vars/dev.yml с http_port: 8080 и enable_tls: false - и тот же самый шаблон рождает другой конфиг. Один .j2, разные окружения. Это и есть динамические конфиги.

Отдельно про {{ ansible_managed }} в первой строке. Это специальная переменная-пометка, что файл сгенерирован Ansible и править руками его бесполезно (затрётся при следующем прогоне). По умолчанию она разворачивается в "Ansible managed", но в ansible.cfg её можно расширить, чтобы видеть имя шаблона, хост и время:

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

[defaults]
ansible_managed = ВНИМАНИЕ: файл сгенерирован Ansible из {file} на {host} - не редактировать руками!
Параметры template module: mode, owner, backup и validate

Сам вызов в плейбуке выглядит так:

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

- name: Развернуть конфиг nginx из шаблона
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: true
    validate: nginx -t -c %s
  notify: Restart nginx
Что тут важно знать про ansible template module:
  • src / dest - откуда шаблон и куда положить результат. Обязательные.
  • owner / group / mode - владелец и права итогового файла. mode пиши строкой в кавычках ('0644'), иначе YAML съест ведущий ноль как восьмеричное число и ты получишь не те права. Это классический срез.
  • backup: true - перед заменой сохранит старую версию рядом с timestamp в имени. Резервная копия создаётся ТОЛЬКО когда файл реально изменился, идемпотентные прогоны мусор не плодят.
  • validate - команда проверки ДО установки. %s - плейсхолдер, куда Ansible подставит путь к временному отрендеренному файлу. Если проверка вернёт не ноль - файл на место НЕ встанет, и ты не положишь битый конфиг, который уронит сервис. Для nginx это nginx -t -c %s, для sshd - /usr/sbin/sshd -t -f %s, для sudoers - visudo -cf %s.
validate - это то, за что ставят галочку на экзамене и в проде. Раскатить сломанный конфиг и положить httpd по всему парку - худший сценарий. Для Apache на RHEL шаблон лёг бы в /etc/httpd/conf.d/, а validate был бы apachectl configtest или httpd -t.

После template обычно идёт notify на хендлер перезапуска сервиса (ansible.builtin.systemd_service или service), плюс на RHEL не забывай про firewalld и SELinux: порт 8080 нестандартный, и SELinux его не пропустит, пока не добавишь его в http_port_t через community.general.seport. На Ubuntu/Debian путей и имён пакетов меньше (nginx тот же, но конфиг в /etc/nginx/sites-available/, апач называется apache2), на RED OS и Astra - всё как в RHEL-семействе и Debian-семействе соответственно.

Типичные грабли
  • mode без кавычек. mode: 0644 в YAML - это число, права получатся кривые. Всегда '0644' строкой.
  • undefined-переменная. Если в шаблоне есть {{ foo }}, а foo нигде не задана, рендеринг падает с "AttributeError" или "is undefined". Лечится фильтром default или проверкой {% if foo is defined %}.
  • Лишние пустые строки от блоков. Строки с {% if %} и {% for %} оставляют после себя перевод строки. Если конфиг чувствителен к этому, включи trim_blocks/lstrip_blocks - в Ansible они по умолчанию включены для template, но в кастомных окружениях проверь. Минус-синтаксис {%- ... -%} тоже подрезает пробелы.
  • Забыл .j2 положить в templates/. В роли шаблоны живут строго в templates/, иначе src его не найдёт.
  • Перепутал template и copy. Положил конфиг с {{ }} через copy - и на сервере остались голые двойные скобки, потому что copy ничего не рендерит. Конфиги с переменными - только через template.
Мини-лаба: повтори руками
  • Создай роль: ansible-galaxy role init webconf. Внутри будет каталог templates/.
  • Положи в templates/nginx.conf.j2 шаблон из урока с переменной http_port, фактом processor_vcpus, условием enable_tls и циклом по upstreams.
  • Заведи group_vars/dev.yml и group_vars/prod.yml с разными значениями http_port и enable_tls.
  • Напиши задачу template с mode: '0644', backup: true и validate: nginx -t -c %s.
  • Прогони на dev и prod, сравни результат: cat /etc/nginx/nginx.conf на обоих узлах должен отличаться, хотя шаблон один.
  • Сломай шаблон специально (убери закрывающую скобку в server-блоке) и убедись, что validate не дал положить битый файл.
  • Поменяй значение переменной, прогони ещё раз - проверь, что появился .backup-файл, а при повторном прогоне без изменений - changed=0.
Контрольные вопросы
  • Чем template принципиально отличается от copy и в каком случае что использовать?
  • Что делает параметр validate и почему %s в команде обязателен? Приведи команду проверки для sshd_config.
  • Зачем mode писать строкой '0644', а не числом 0644?
  • Как внутри .j2 подставить факт о числе ядер и как защититься от необъявленной переменной?
Итог

template = copy + движок Jinja2: один .j2-шаблон с переменными, фактами, циклами и условиями превращается в правильный конфиг на каждом узле. Запомни связку owner/group/mode (строкой), backup для отката и validate для защиты от битых конфигов, плюс {{ ansible_managed }} как пометку автогенерации. На RHCE/EX294 template встречается почти всегда - чаще всего просят раскатить конфиг сервиса из шаблона по переменным окружения, и именно validate с правильными правами отделяет зачёт от провала.
👍4 ❤️3 🔥1 😄 🤔3
Аватара пользователя
rkshark
Сообщения: 1
Зарегистрирован: 19 май 2026, 11:01

Re: Шаблоны Jinja2: модуль template и динамические конфиги

Сообщение rkshark »

Наконец дошло чем template от copy отличается - я раньше через copy конфиг с переменными кидал и не понимал почему на сервере {{ }} остаются. Спасибо, validate с nginx -t вообще спас, поймал кривой апстрим до выката.
👍 ❤️ 🔥 😄 🤔3
Аватара пользователя
Pazzkrew
Сообщения: 1
Зарегистрирован: 04 июн 2026, 12:34

Re: Шаблоны Jinja2: модуль template и динамические конфиги

Сообщение Pazzkrew »

Вопрос по mode: а если я realpath забыл и mode числом 0644 написал - какие права реально встанут? И validate для sudoers это visudo -cf %s, я правильно понял из урока?
👍3 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Точечное редактирование файлов: lineinfile и blockinfile
Следующая глава →
Jinja2 продвинуто: фильтры, циклы, макросы и lookup

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

Поделиться темой: ✈ Telegram VK
  • Похожие темы
Похожие запросы: jinja2 шаблоны ansible как сделать динамический конфигкак создать роль ansible с нуля и структура каталогов

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

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

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