如何使用 Ansible 在目标主机上通过文件模板生成文件?这对于服务配置文件、占位符网页、报告等场景非常有用。 接下来,我将通过简单的 Ansible 代码为您演示。 我是 Luca Berton,欢迎收看今天的 Ansible Pilot 节目。

在文件模板中使用 Ansible 循环

ansible.builtin.template 将模板文件渲染到目标主机。 模板通过 Jinja2 模板语言处理。 此外,你还可以在模板中使用一些特殊变量:ansible_managed、template_host、template_uid、template_path、template_fullpath、template_destpath 和 template_run_date。 它支持多种操作系统。 对于简单的文本格式化,可以使用 Ansible 的 ansible.builtin.copy 模块;对于创建空文件,可以使用 ansible.builtin.file 模块。 对于 Windows 系统,建议使用 ansible.windows.win_template 模块。

参数

  • src(路径):模板文件路径(通常位于“templates/”目录)
  • dest(路径):目标路径
  • validate(字符串):在复制到目标路径之前运行的验证命令(使用“%s”占位符)
  • backup(布尔值):是否创建备份文件
  • mode/owner/group:文件权限
  • setype/seuser/selevel:SELinux 属性

让我重点介绍模板模块中最常用的参数。 唯一必需的参数是“src”和“dest”。 “src”参数指定模板文件的名称。模板通常存储在“templates”目录下,文件扩展名为“.j2”。 “dest”参数指定在远程机器上渲染模板的路径。 “validate”参数允许你指定在将文件复制到目标位置之前运行的验证命令,这对于服务配置文件非常有用。 请注意,特殊转义序列“%s”将被 Ansible 替换为目标路径。 如果启用“backup”参数,Ansible 会在将文件复制到目标位置之前创建一个包含时间戳信息的备份文件。 我们还可以指定文件权限和 SELinux 属性。

示例:使用 Ansible Playbook 在文件模板中使用循环

代码文件: generate_myhosts.yml

---
- name: template module demo
  hosts: all
  become: true
  tasks:
    - name: generate /etc/myhosts file
      ansible.builtin.template:
        src: templates/hosts.j2
        dest: /etc/myhosts
        owner: root
        group: root
        mode: '0644'

模板文件: templates/hosts.j2

# {{ ansible_managed }}
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_host'] }} {{ hostvars[host]['inventory_hostname'] }} {{ hostvars[host]['inventory_hostname_short'] }}
{% endfor %}

执行命令:

$ ansible-playbook -i apply_template/inventory apply_template/generate_myhosts.yml

执行结果:

PLAY [template module demo] ******************************************

TASK [Gathering Facts] ***********************************************
ok: [demo.example.com]

TASK [generate /etc/myhosts file] ************************************
changed: [demo.example.com]

PLAY RECAP ************************************************************
demo.example.com           : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

执行前的状态

$ ssh devops@demo.example.com
Last login: Tue Nov 23 17:10:30 2021 from 192.168.0.101
[devops@demo ~]$ sudo su
[root@demo devops]# ls -al /etc/myhosts
ls: cannot access '/etc/myhosts': No such file or directory

执行后的状态

$ ssh devops@demo.example.com
Last login: Tue Nov 23 17:32:39 2021 from 192.168.0.101
[devops@demo ~]$ sudo su
[root@demo devops]# ls -al /etc/myhosts 
-rw-r--r--. 1 root root 214 Nov 23 17:32 /etc/myhosts
[root@demo devops]# cat /etc/myhosts 
# Ansible managed
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.190  demo.example.com demo
[devops@demo ~]$ exit
logout
Connection to demo.example.com closed.

Ansible 主机清单文件内容

$ cat apply_template/inventory 
demo.example.com ansible_host=192.168.0.190

[all:vars]
ansible_connection=ssh
ansible_user=devops