Короткий ответ
Нужно создать .j2-шаблон с циклом {% for %} по списку переменной (например, upstream_servers) и условием {% if gzip_enabled %} для опциональных блоков, подключить его через модуль ansible.builtin.template с указанием src/dest; для диагностики используется ansible-playbook --check --diff (покажет построчный diff без применения) или прогон модуля template в режиме с -vvv, а также точечная проверка конкретных значений переменных через ansible -m debug -a "var=upstream_servers".
Как это работает подробнее
модуль template рендерит Jinja2-шаблон на управляющей машине (control node), подставляя значения переменных, доступных для конкретного хоста (из inventory, group_vars, host_vars, facts), и копирует результат на целевой хост, сравнивая содержимое с уже существующим файлом для определения changed/ok; то есть вся логика выбора данных решается до копирования файла, а не на самом хосте.
Пример кода
{# roles/nginx/templates/nginx.conf.j2 #}
upstream backend {
{% for srv in upstream_servers %}
server {{ srv }};
{% endfor %}
}
{% if gzip_enabled | default(false) %}
gzip on;
{% endif %}
$ ansible-playbook site.yml --check --diff --limit web01
--- before: /etc/nginx/nginx.conf
+++ after: /etc/nginx/nginx.conf
+upstream backend {
+ server 10.0.1.10:8080;
+ server 10.0.1.11:8080;
+}Что использовать на практике
- Практика. при отладке шаблона полезно временно вывести промежуточное значение через
{{ upstream_servers | to_nice_json }}в комментарии шаблона или прогнатьansible-playbook --check --diff --limit host1, чтобы увидеть точный diff без изменения продакшен-хоста; также стоит держать тестовые значения переменных в отдельном inventory для проверки edge-кейсов (пустой список upstream, один сервер, много серверов).
Подводные камни
- Ошибка. частая ошибка — использовать неопределённую переменную в шаблоне без дефолта (
{{ gzip_enabled }}вместо{{ gzip_enabled | default(false) }}), из-за чего на хостах без явного значения рендер падает с ошибкойundefined variable; другая ошибка — забыть, что группировка переменных в Ansible имеет приоритет (host_vars выше group_vars выше defaults роли), и не проверить, что нужное значение не перекрывается более специфичной переменной.