Ansible模板中用Jinja2实现循环与判断需先校验变量存在性并设默认值,再用{% for %}遍历生成Nginx upstream配置,用{% if %}控制条件段启用,支持嵌套结构处理字典列表,并注意防未定义变量、空列表异常及敏感信息泄露。

在 Ansible 的 template 模块中使用 Jinja2 语法实现循环与判断,核心是写对模板文件(如 nginx.conf.j2)里的 {% for %} 和 {% if %} 结构,同时确保 Playbook 中传入的数据结构合理、安全。
用 for 循环遍历主机列表生成 upstream 配置
常见于 Nginx 负载均衡配置。假设你有 inventory 分组 backend,想为每个后端主机生成一行 server 指令:
- 模板中写法要先判断分组是否存在且非空,避免渲染失败:
{% if groups['backend'] is defined and groups['backend'] %}
upstream app_servers {
{% for host in groups['backend'] %}
server {{ hostvars[host]['ansible_host'] }}:{{ upstream_port | default(8080) }};
{% endfor %}
}
{% endif %}
-
upstream_port是变量,加| default(8080)防止未定义时报错 - 即使
backend组为空,也能生成合法的空upstream块,不中断部署
用 if 判断控制配置段是否启用
比如只在特定环境(如 prod)中开启 access_log,或根据系统类型调整参数:
- 检查变量是否存在并为真:
{% if enable_ssl %} ssl on; {% endif %} - 判断系统发行版:
{% if ansible_facts['distribution'] == 'CentOS' %} include /etc/nginx/conf.d/centos-specific.conf; {% endif %} - 组合多个条件:
{% if env == 'prod' and use_cache %} proxy_cache my_cache; {% endif %}
嵌套循环与条件组合处理复杂数据
当变量是字典列表(如多个虚拟主机配置),可用双层结构:
- 模板示例:
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.port | default(80) }};
server_name {{ vhost.server_name }};
root {{ vhost.root }};
{% if vhost.ssl_enabled %}
ssl_certificate {{ vhost.ssl_cert }};
ssl_certificate_key {{ vhost.ssl_key }};
{% endif %}
}
{% endfor %}
-
nginx_vhosts是 Playbook 中定义的列表,每个元素是含port、server_name等键的字典 - 每个
vhost独立判断是否启用 SSL,互不影响
注意边界与安全写法
模板里没有运行时错误捕获机制,出错直接导致任务失败。务必预防以下问题:
- 访问未定义变量:用
is defined或过滤器| default('')兜底 - 空列表导致循环异常:始终用
{% if list_var %} ... {% for %} ... {% endif %}包裹 - 敏感信息泄露:避免在模板中直接输出密码类变量,改用
lookup('env', '...')或 vault 加密变量 - 缩进和换行:Jinja2 对空白敏感,多用
{%-和-%}去除多余空行,提升配置可读性











