Ansible读取CSV渲染模板异常:所有服务器均应用最后一行数据
问题:Ansible渲染模板时所有服务器均应用CSV最后一行数据
我通过CSV文件获取数据,用Ansible渲染模板后复制到远程服务器,但每台服务器都会遍历整个CSV文件,最终所有服务器的配置文件都只应用了CSV的最后一行数据,而非对应行的数据。
相关文件内容
test.csv
Application,env,Datacenter,Hostname Microsoft,Test,DC1,testserver1 Apple,Test,DC2,testserver2
原main.yml
- name: read csv read_csv: path: /u00/app/monitor/test.csv key: Hostname register: newrelic - name: Print newrelic var ansible.builtin.debug: var: newrelic.dict[inventory_hostname] - name: copy template template: src: /u00/ansible/Playbooks/files/infra-config.yml_template dest: /u00/app/monitor/infra-config.yml loop: "{{ newrelic.list }}" - name: Start the New Relic Service ansible.builtin.systemd: name: newrelic-infra.service state: started become: yes become_user: root
模板文件infra-config.yml_template
custom_attributes: application : {{ item.Application }} env : {{ item.env }} datacenter : {{ item.Datacenter }} log: file: /u00/app/monitor/infra.log
预期与实际结果
预期结果
testserver1应用CSV第一行数据,testserver2应用第二行数据:
# ssh admin@testserver1 cat infra-config.yml custom_attributes: application : Microsoft env : Test datacenter : DC1 log: file: /u00/app/monitor/infra.log # ssh admin@testserver2 cat infra-config.yml custom_attributes: application : Apple env : Test datacenter : DC2 log: file: /u00/app/monitor/infra.log
实际结果
所有服务器均应用CSV最后一行数据:
# ssh admin@testserver1 cat infra-config.yml custom_attributes: application : Apple env : Test datacenter : DC2 log: file: /u00/app/monitor/infra.log # ssh admin@testserver2 cat infra-config.yml custom_attributes: application : Apple env : Test datacenter : DC2 log: file: /u00/app/monitor/infra.log
问题原因
原Playbook中使用loop: "{{ newrelic.list }}"遍历整个CSV条目列表,导致每台服务器都会执行多次模板复制操作,后一次写入的内容会覆盖前一次,最终所有服务器的配置文件都保留了CSV最后一行的数据。
实际上你已经通过key: Hostname参数将CSV数据转换为以主机名为键的字典newrelic.dict,完全可以直接匹配当前服务器的主机名,获取对应的数据条目,不需要遍历整个列表。
修正后的Playbook
修改copy template任务,去掉loop,直接引用当前主机对应的CSV条目:
- name: read csv read_csv: path: /u00/app/monitor/test.csv key: Hostname register: newrelic - name: Print newrelic var ansible.builtin.debug: var: newrelic.dict[inventory_hostname] - name: copy template template: src: /u00/ansible/Playbooks/files/infra-config.yml_template dest: /u00/app/monitor/infra-config.yml vars: item: "{{ newrelic.dict[inventory_hostname] }}" - name: Start the New Relic Service ansible.builtin.systemd: name: newrelic-infra.service state: started become: yes become_user: root
另一种修改方式(调整模板)
也可以直接修改模板中的变量引用,不需要在任务里定义item变量:
custom_attributes: application : {{ newrelic.dict[inventory_hostname].Application }} env : {{ newrelic.dict[inventory_hostname].env }} datacenter : {{ newrelic.dict[inventory_hostname].Datacenter }} log: file: /u00/app/monitor/infra.log
对应的任务简化为:
- name: copy template template: src: /u00/ansible/Playbooks/files/infra-config.yml_template dest: /u00/app/monitor/infra-config.yml
验证结果
修正后,每台服务器会根据自身主机名匹配CSV中的对应条目,生成符合预期的配置文件。
内容的提问来源于stack exchange,提问作者Lucky Ameta
相关产品推荐
相关产品推荐

