介绍
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 指定文件,确认渲染结果。
注意事项 & 坑
引号与YAML冲突
playbook里mode权限必须加引号mode: '0644',否则yaml会把0644当成八进制解析出错。缩进问题
Jinja2的缩进不强制,渲染后输出文本的缩进由模板内写的空格决定。Jinja2控制语句
{% %}的缩进和生成的配置文件缩进相互独立,容易出现配置文件错乱。特殊字符转义
如{{ }}、%要原样写入配置文件(例如prometheus、grafana配置),需要raw块{% raw %} # 原样输出,不解析jinja语法 {{ metric_name }} {% endraw %}变量优先级
模板内变量遵循ansible完整变量优先级(extra vars > host_vars > group_vars > play vars)。换行控制
-减号{%-去除前面空白换行;-%}去除后面空白换行,用来清理多余空行{%- if env == 'prod' %} worker_processes auto; {%- endif %}
template vs copy vs file
| 模块 | 作用 |
|---|---|
copy |
直接复制文件,不渲染jinja2 |
template |
渲染jinja2模板后传输文件 |
file |
仅创建目录、修改权限,不传输内容 |