基于Jinja2模板与变量文件批量生成配置文件的问题排查
问题说明
我尝试用Jinja2模板文件(server.properties)结合变量文件(common.yml)批量生成多个配置文件,目前文件能正常创建,但只有第一个变量生效,其余变量未在模板中正确渲染。需要生成server1.properties和server2.properties两个文件,每个文件对应节点的配置信息,例如server1.properties的期望输出如下:
node.id= 1 controller.quorum.voters= 1@web.example.com:8080,2@web.example.com:8081,3@web.example.com:8082 ############################# Socket Server Settings ############################# listeners= SASL_SSL://web.example.com:18080,CONTROLLER://web.example.com:8080 advertised.listeners= SASL_SSL://web.example.com:18080 ############################# Log Basics ############################# log.dirs= /tmp/server1/kraft-combined-logs
现有文件内容
Main.yml
--- - name: Create server properties files hosts: localhost become: yes become_user: root gather_facts: true vars: t_file: server.properties t_dir: /path/to/save/newfiles tasks: - name: Include vars file include_vars: file: common.yml name: common - name: Creating template file - server.properties.j2 template: src: "{{ t_file }}" dest: 'server.properties.j2'
common.yml
--- server: - server_no: 1 - server_no: 2 node_id: - node_id: 1 - node_id: 2 cqvoters: - cq_voters: 1@web.example.com:8080,2@web.example.com:8081,3@web.example.com:8082 - cq_voters: 1@web.example.com:8080,2@web.example.com:8081,3@web.example.com:8082 listeners: - listeners: SASL_SSL://web.example.com:18080,CONTROLLER://web.example.com:8080 - listeners: SASL_SSL://web.example.com:18081,CONTROLLER://web.example.com:8081 advertised: - advertised_listeners: SASL_SSL://web.example.com:18080 - advertised_listeners: SASL_SSL://web.example.com:18081 log_dir: - log_dir: /tmp/server1/kraft-combined-logs - log_dir: /tmp/server2/kraft-combined-logs
server.properties(模板文件)
node.id= "{{ node_id }}" controller.quorum.voters= "{{ cqvoters }}" ############################# Socket Server Settings ############################# listeners= "{{ listeners }}" advertised.listeners= "{{ advertised }}" ############################# Log Basics ############################# log.dirs= "{{ log_dir }}"
解决方案
问题根源在于变量结构设计不合理:每个配置项单独维护成列表,无法保证循环时各列表的索引对应正确,且现有Playbook没有做循环遍历生成多个文件的逻辑。以下是修正步骤:
1. 重构变量文件common.yml
将每个服务器的所有配置整合成一个列表项,确保每个服务器的参数绑定在一起:
--- servers: - server_no: 1 node_id: 1 cq_voters: 1@web.example.com:8080,2@web.example.com:8081,3@web.example.com:8082 listeners: SASL_SSL://web.example.com:18080,CONTROLLER://web.example.com:8080 advertised_listeners: SASL_SSL://web.example.com:18080 log_dir: /tmp/server1/kraft-combined-logs - server_no: 2 node_id: 2 cq_voters: 1@web.example.com:8080,2@web.example.com:8081,3@web.example.com:8082 listeners: SASL_SSL://web.example.com:18081,CONTROLLER://web.example.com:8081 advertised_listeners: SASL_SSL://web.example.com:18081 log_dir: /tmp/server2/kraft-combined-logs
2. 修改Main.yml的Playbook逻辑
添加循环遍历servers列表,每次渲染模板生成对应服务器的配置文件:
--- - name: Create server properties files hosts: localhost become: yes become_user: root gather_facts: true vars: t_file: server.properties.j2 # 模板文件名改为j2后缀更规范 t_dir: /path/to/save/newfiles tasks: - name: Include vars file include_vars: file: common.yml - name: Generate server properties files template: src: "{{ t_file }}" dest: "{{ t_dir }}/server{{ item.server_no }}.properties" mode: 0644 loop: "{{ servers }}" # 将当前循环项的参数传递给模板 vars: node_id: "{{ item.node_id }}" cqvoters: "{{ item.cq_voters }}" listeners: "{{ item.listeners }}" advertised: "{{ item.advertised_listeners }}" log_dir: "{{ item.log_dir }}"
3. 修正模板文件server.properties.j2
去掉多余的引号,直接引用变量(Jinja2渲染时会自动替换为实际值):
node.id= {{ node_id }} controller.quorum.voters= {{ cqvoters }} ############################# Socket Server Settings ############################# listeners= {{ listeners }} advertised.listeners= {{ advertised }} ############################# Log Basics ############################# log.dirs= {{ log_dir }}
内容的提问来源于stack exchange,提问作者Arun Karthick V
相关产品推荐
相关产品推荐

