用 Jinja2 生成配置文件
目标
把不同环境的配置文件拆分为一个模板和多组数据,确保渲染结果整洁、经过验证后再部署。
为什么重要
如果为每个环境各维护一份配置文件,这些文件最终一定会彼此偏离。模板通过“结构一份、数据多份”消除这种分叉。实际工作中,破坏模板的往往不是语法,而是两个问题。其一是空白——控制语句留下的空行可能破坏 YAML 配置。其二是每次都不同的渲染结果——仅仅一行时间戳就会让文件在每次运行时改变,进而每次都触发 handler 并重启服务。最后,validate 是阻止错误配置导致服务宕机的最低成本安全措施。一旦启用自动部署,这个选项就不再是可选项。
步骤
- 本实验只使用一个 playbook:
/root/ans/tpl/site.yml。通过/root/ans/tpl/templates/basic.j2创建/root/ans/tpl/out/basic.conf,结果中必须有service = checkout行。 - 通过
/root/ans/tpl/templates/filters.j2创建/root/ans/tpl/out/filters.conf,输出三行:UPPER=CHECKOUT、TIMEOUT=30(未定义变量的默认值)、REPLICAS=3。 - 通过
/root/ans/tpl/templates/upstream.j2创建/root/ans/tpl/out/upstream.conf。三个后端要分别以server 10.0.0.11:8080;的形式各占一行。 - 用不同变量渲染同一个模板,创建
/root/ans/tpl/out/prod.conf(tls = on,无 debug)和/root/ans/tpl/out/dev.conf(tls = off,有 debug)。 - 控制空白,使
upstream.conf中没有任何空行,server行前也没有多余缩进。可以使用{%- -%},或在/root/ans/tpl/site.yml的templatetask 中启用trim_blocks/lstrip_blocks。 - 通过
/root/ans/tpl/templates/node.j2创建/root/ans/tpl/out/node.conf。hostname、arch来自 fact,generated_for来自inventory_hostname(=web1)。 - 在
/root/ans/tpl/site.yml的templatetask 中加入validate和backup: true,创建/root/ans/tpl/out/validated.conf。内容只有一行key=value。 - 创建
/root/ans/tpl/out/site.nginx。在upstream checkout_backend {块内放入 3 行缩进 4 个空格的server,并分别加入缩进 4 个空格的listen 8080;和server_name checkout.labhub.internal;。空行不得超过 1 行。
参考
- 每个实验都会启动全新的实验 Pod。如果
/root/ans/inventory/hosts.ini不存在,请先重新创建与第一个实验相同的 inventory(web1·web2·db1,ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root,并在[prod:children]中加入 web·db)。结构可以参考/opt/lab/fixtures/ansible/inventory.sample.ini。 template模块的src接受相对于 role/playbook 的路径,dest接受目标路径。- 过滤器可以连续使用:
{{ name | default('unknown') | upper }} - 常见错误 1:直接保留
{% for %},导致结果中出现空行。 - 常见错误 2:在模板中加入时间或随机值,使每次结果都不同,从而破坏幂等性。
渲染带变量的基础模板
本实验只使用一个 playbook:/root/ans/tpl/site.yml。通过 /root/ans/tpl/templates/basic.j2 创建 /root/ans/tpl/out/basic.conf,结果中必须有 service = checkout 行。
使用 {{ 변수 }} 输出值。如果结果中仍有 Jinja2 语法,说明尚未完成渲染。
使用 upper 和 default 过滤器
通过 /root/ans/tpl/templates/filters.j2 创建 /root/ans/tpl/out/filters.conf,输出三行:UPPER=CHECKOUT、TIMEOUT=30(未定义变量的默认值)、REPLICAS=3。
过滤器使用管道连接。想一想,哪个过滤器可以为未定义变量提供默认值。
添加遍历列表的循环
通过 /root/ans/tpl/templates/upstream.j2 创建 /root/ans/tpl/out/upstream.conf。三个后端要分别以 server 10.0.0.11:8080; 的形式各占一行。
在 {% for %} 与 {% endfor %} 之间放入需要重复的行。三个后端必须各占一行。
按环境输出不同配置
用不同变量渲染同一个模板,创建 /root/ans/tpl/out/prod.conf(tls = on,无 debug)和 /root/ans/tpl/out/dev.conf(tls = off,有 debug)。
用不同变量渲染同一模板两次。prod 中不得出现 debug。
通过空白控制消除空行
控制空白,使 upstream.conf 中没有任何空行,server 行前也没有多余缩进。可以使用 {%- -%},或在 /root/ans/tpl/site.yml 的 template task 中启用 trim_blocks/lstrip_blocks。
使用 {%- / -%},或 template 模块的 trim_blocks/lstrip_blocks。结果中不能有任何空行。
在模板中使用 fact 和 inventory_hostname
通过 /root/ans/tpl/templates/node.j2 创建 /root/ans/tpl/out/node.conf。hostname、arch 来自 fact,generated_for 来自 inventory_hostname(=web1)。
fact 变量以 ansible_ 开头,目标名称则是 inventory_hostname。
添加 validate 和 backup
在 /root/ans/tpl/site.yml 的 template task 中加入 validate 和 backup: true,创建 /root/ans/tpl/out/validated.conf。内容只有一行 key=value。
validate 会把临时文件路径放入 %s。如果校验失败,文件就不会被部署。
用组变量生成完整 nginx 配置
创建 /root/ans/tpl/out/site.nginx。在 upstream checkout_backend { 块内放入 3 行缩进 4 个空格的 server,并分别加入缩进 4 个空格的 listen 8080; 和 server_name checkout.labhub.internal;。空行不得超过 1 行。
upstream 块中的 server 行需要缩进 4 个空格。请结合使用空白控制和循环。