Ansible教程:Jinja2 模板介绍、语法

介绍

Ansible 的模板基于 Jinja2 模板引擎,文件后缀一般为 .j2。核心用途:把变量、事实(facts)、循环、判断逻辑注入配置文件,动态生成目标主机上的配置,常用于 Nginx、MySQL、系统配置等文件分发。

模块

template 模块(区别于 copy:copy直接复制文件;template会渲染jinja2语法后再传到远端)

应用场景

生成配置文件(最常用)

  • Nginx/Apache:循环批量生成多个 server {} 虚拟主机块;根据环境变量动态开关配置项。

  • MySQL:不同主机内存不一样,动态计算 innodb_buffer_pool_size;prod 开启慢查询,测试环境关闭。

  • Redis:根据主机内存设置 maxmemory;不同集群节点生成不同 redis.conf(不同 port、cluster-node-id)。

生成脚本文件

shell、bash、python 启动脚本,渲染变量后传到远端,再赋予执行权限

生成清单、报告

中控机或远端生成主机巡检报告、hosts 文件、静态 inventory

语法

1. 三种定界符

1. 变量输出:{{ 表达式 }} 渲染输出值
{{ nginx_port }}
2. 逻辑控制

{% 语句 %} 不输出内容,用于 if / for 等

{% if nginx_enable %}
listen {{ nginx_port }};
{% endif %}
3. 注释

{# 注释内容 #} ,渲染后会被删除,不会出现在目标文件

{# 这是nginx监听端口,不要修改 #}

3. 条件判断 if / elif / else

{% if env == "prod" %}
worker_processes auto;
{% elif env == "test" %}
worker_processes 2;
{% else %}
worker_processes 1;
{% endif %}

支持逻辑运算符:and、or、not,比较 == != > < >= <=

4. 循环 for

{# 遍历列表 #}
{% for site in sites %}
server {
    server_name {{ site.name }};
    root {{ site.root }};
}
{% endfor %}

循环内置变量:

  • loop.index:从1开始计数
  • loop.index0:从0开始计数
  • loop.first:布尔值,是否第一次循环
  • loop.last:布尔值,是否最后一次循环
    {% for site in sites %}
    # {{ loop.index }} 站点
    server_name {{ site.name }};
    {% endfor %}
    

循环 + if 过滤

{% for site in sites if site.enable %}
server_name {{ site.name }};
{% endfor %}

模板调试

1. 单独渲染模板(不推送到远端)

ansible localhost -m ansible.builtin.template -a "src=test.j2 dest=/tmp/out"

2. debug模块查看变量,排查模板取值问题

- name: 打印变量
  ansible.builtin.debug:
    msg: "{{ sites }}"

3. 查看渲染完成后的文件

登录目标主机查看 dest 指定文件,确认渲染结果。

注意事项 & 坑

  1. 引号与YAML冲突
    playbook里mode权限必须加引号 mode: '0644',否则yaml会把0644当成八进制解析出错。

  2. 缩进问题
    Jinja2的缩进不强制,渲染后输出文本的缩进由模板内写的空格决定。

    Jinja2控制语句 {% %} 的缩进和生成的配置文件缩进相互独立,容易出现配置文件错乱。

  3. 特殊字符转义
    如 {{ }}、% 要原样写入配置文件(例如prometheus、grafana配置),需要raw块

    {% raw %}
    # 原样输出,不解析jinja语法
    {{ metric_name }}
    {% endraw %}
    
  4. 变量优先级
    模板内变量遵循ansible完整变量优先级(extra vars > host_vars > group_vars > play vars)。

  5. 换行控制 - 减号
    {%- 去除前面空白换行;-%} 去除后面空白换行,用来清理多余空行

    {%- if env == 'prod' %}
    worker_processes auto;
    {%- endif %}
    

template vs copy vs file

模块 作用
copy 直接复制文件,不渲染jinja2
template 渲染jinja2模板后传输文件
file 仅创建目录、修改权限,不传输内容