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

Шаблоны Jinja2 в Ansible: первые шаги

Аннотация Если ты устал править конфиги руками под каждый сервер, а в плейбуках всё ещё везде copy, то самое время познакомиться с шаблонами. В этой статье разберём, что такое шаблоны Jinja2 в Ansible, почему модуль template удобнее, чем copy, как подставлять переменные ({{ my_var }}), писать простой if и for прямо внутри файла и использовать пару полезных фильтров (default, upper, lower, join). Зачем вообще нужны шаблоны Jinja2 Боль классическая: один и тот же конфиг на десятках серверов; везде одинаковая структура, меняются только 2–3 параметра; ты копируешь почти одинаковые файлы, легко ошибиться и забыть где-то что-то поменять. Шаблон Jinja2 — это «живой» конфиг, в котором вместо жёстко забитых значений стоят переменные и маленькие кусочки логики. Ansible подставляет значения переменных и на выходе даёт обычный текстовый файл — но уже под конкретный сервер. template vs copy простыми словами Что делает copy copy просто берёт файл с твоей машины (или из роли) и как есть кладёт его н
Оглавление

Аннотация

Если ты устал править конфиги руками под каждый сервер, а в плейбуках всё ещё везде copy, то самое время познакомиться с шаблонами. В этой статье разберём, что такое шаблоны Jinja2 в Ansible, почему модуль template удобнее, чем copy, как подставлять переменные ({{ my_var }}), писать простой if и for прямо внутри файла и использовать пару полезных фильтров (default, upper, lower, join).

Зачем вообще нужны шаблоны Jinja2

Боль классическая:

  • один и тот же конфиг на десятках серверов;
  • везде одинаковая структура, меняются только 2–3 параметра;
  • ты копируешь почти одинаковые файлы, легко ошибиться и забыть где-то что-то поменять.

Шаблон Jinja2 — это «живой» конфиг, в котором вместо жёстко забитых значений стоят переменные и маленькие кусочки логики. Ansible подставляет значения переменных и на выходе даёт обычный текстовый файл — но уже под конкретный сервер.

template vs copy простыми словами

Что делает copy

copy просто берёт файл с твоей машины (или из роли) и как есть кладёт его на целевой сервер:

-2

Если нужно поменять порт — ты правишь myapp.conf, перезапускаешь плейбук.

А если порт зависит от окружения (
dev/prod) — начинаются копии файлов: myapp.dev.conf, myapp.prod.conf и так далее.

Что делает template

template берёт шаблон (обычно с расширением .j2), подставляет в него переменные и только потом копирует на сервер:

-3

Внутри myapp.conf.j2 уже не «жёсткий» текст, а что-то вроде:

-4

И для каждого хоста получится свой файл — только за счёт разных переменных.

Итог:
copy — статичный файл.
template — файл с переменными и логикой, из которого Ansible собирает итоговый конфиг.

Первый простой шаблон: подставляем {{ my_var }}

Допустим, мы хотим положить простой конфиг приложения:

1. Определяем переменные

Где-то в переменных (например, group_vars/app.yml):

-5

2. Пишем шаблон templates/myapp.conf.j2

-6

Обрати внимание на двойные фигурные скобки: {{ ... }} — это место для переменной.

3. Задача в плейбуке

-7

4. Что получится на сервере

На целевом хосте файл /etc/myapp.conf будет выглядеть так:

-8

Если для другого окружения ты задашь myapp_port: 9090 и myapp_env: "prod", шаблон станет тем же, а итоговый файл поменяется — магия без копипасты.

Минимум логики: if внутри шаблона

Иногда нужно включать/выключать куски конфига. Например, включать debug-лог только в dev.

Переменная

-9

Шаблон myapp.conf.j2 с if

-10

Разбираем:

  • {% if ... %} / {% else %} / {% endif %} — управляющие конструкции Jinja2;
  • эти строки не попадут в итоговый файл, они только управляют тем, какой текст вывести.

Результат, если myapp_debug: true:

-11

Результат, если myapp_debug: false:

-12

Чуть логики побольше: for внутри шаблона

Ещё один частый кейс — генерировать повторяющиеся строки по списку. Например, список серверов для подключения.

Переменная-список

-13

Шаблон myapp.conf.j2 с for

-14

Итоговый файл:

-15

Ты добавляешь новый сервер только в списке переменных — шаблон сам подстроится.

Полезные фильтры: default, upper, lower, join

Фильтр — это «функция» после переменной, которая её немного изменяет. Записывается через | (палочку).

default: значение по умолчанию

Если переменная не задана — подставить безопасное значение.

-16

Если myapp_env нет — будет dev.
Так удобно не получать ошибку из-за забытой переменной.

upper: в верхний регистр

-17

"dev" превратится в "DEV".

lower: в нижний регистр

-18

"PROD" превратится в "prod".

join: собрать список в строку

У нас был список:

-19

В шаблоне:

-20

Итог:

-21

Очень удобно для списков IP, фичей, флагов.

Типичные подводные камни

1. Путаем YAML и Jinja2

В плейбуке:

-22

Так писать нельзяYAML подумает, что это мусор.

Нужно:

-23

То есть в YAML — всегда берём Jinja2 в кавычки.

2. Забыли расширение .j2

Технически шаблон может называться как угодно, но расширение .j2:

  • помогает самому не запутаться;
  • даёт подсветку синтаксиса в редакторе.

3. Переменная не задана и всё падает

Если переменная обязательна — пусть падает.

Если необязательная — используй default:

-24

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

  • Ansible прогоняет шаблон через движок Jinja2: подставляет переменные, выполняет if/for, применяет фильтры.
  • На выходе получается обычный текстовый файл — конфиг, который понимает твой сервис.
  • Вся «магия» живёт в одном месте: шаблон + переменные. Не нужно плодить кучу почти одинаковых конфигов.
  • Логика в шаблоне остаётся простой: условие, цикл, парочка фильтров — этого уже достаточно, чтобы закрыть 80% реальных задач.

Что сделали в этой статье

  • Разобрали, чем template удобнее, чем copy, когда речь про конфиги.
  • Написали первый простой шаблон с подстановкой переменных {{ my_var }}.
  • Посмотрели, как использовать if и for прямо внутри файла.
  • Разобрали базовые фильтры Jinja2: default, upper, lower, join.
  • Отметили типичные ошибки, которые мешают шаблонам работать.

Сделать прямо сейчас (чеклист)

  1. Найди в своих плейбуках место, где copy кладёт почти одинаковый конфиг на разные хосты.
  2. Переименуй файл в *.j2 и замени «жёсткие» значения на переменные {{ ... }}.
  3. Задай эти переменные в group_vars или host_vars для разных окружений.
  4. Заменить copy на template и запусти плейбук.
  5. Открой конфиг на целевом хосте и убедись, что значения действительно разные и берутся из переменных.

CTA

Если тебе зашла эта подача Ansible «без магии и боли» — подпишись на серию про Ansible в Дзене.

Пиши в комментариях:

  • где шаблоны уже выручили;
  • или скинь кусочек своего конфига — разберём, как превратить его в аккуратный Jinja2-шаблон.