2. 使用变量和模板动态生成配置文件

任务目标

编写一个Ansible Playbook,使用变量结合Jinja2模板,为不同主机动态生成Nginx站点配置文件。要求根据每台主机的inventory_hostname自动设置server_name,并将模板渲染后的文件部署到目标主机的Nginx配置目录。

环境准备

  • 控制端已安装Ansible 2.9+
  • 目标主机为Linux,已安装Nginx(本例仅生成配置文件,不执行服务重启)
  • 控制端与目标主机已配置SSH免密或使用密码参数

目录结构

nginx_vars_demo/
├── ansible.cfg
├── inventory.ini
├── playbook.yml
└── templates/
    └── nginx_site.conf.j2

关键完整代码

1. inventory.ini — 定义两台主机,分别设置不同的server_port变量:

[web_servers]
web1 ansible_host=192.168.1.101 server_port=8080
web2 ansible_host=192.168.1.102 server_port=9090

2. templates/nginx_site.conf.j2 — Jinja2模板,使用主机名和端口变量:

server {
    listen {{ server_port }};
    server_name {{ inventory_hostname }}.example.com;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

3. playbook.yml — 核心Playbook,渲染模板并部署:

---
- name: Generate Nginx config from template
  hosts: web_servers
  become: yes
  vars:
    nginx_conf_dir: /etc/nginx/conf.d

  tasks:
    - name: Ensure conf.d directory exists
      file:
        path: "{{ nginx_conf_dir }}"
        state: directory

    - name: Deploy templated Nginx site config
      template:
        src: nginx_site.conf.j2
        dest: "{{ nginx_conf_dir }}/{{ inventory_hostname }}.conf"
        owner: root
        group: root
        mode: '0644'
      register: deploy_result

    - name: Show generated config content
      debug:
        msg: "{{ lookup('template', 'nginx_site.conf.j2') }}"
      when: deploy_result.changed

4. ansible.cfg — 最小配置,指定清单文件:

[defaults]
inventory = inventory.ini
host_key_checking = False

运行方式

cd nginx_vars_demo
ansible-playbook playbook.yml

验证方法

  1. Playbook执行结果:观察每个task是否显示ok或changed,无failed。
  2. 目标主机文件检查:登录web1执行cat /etc/nginx/conf.d/web1.conf,应看到server_name web1.example.com;和listen 8080;;登录web2执行同样命令,应看到server_name web2.example.com;和listen 9090;。
  3. 语法校验:在目标主机执行nginx -t,输出syntax is ok且test is successful即通过。

预期输出示例

当Playbook执行成功后,web1上生成的/etc/nginx/conf.d/web1.conf内容为:

server {
    listen 8080;
    server_name web1.example.com;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

常见问题

  • 模板未生效:确认templates/目录与playbook.yml同级,且模板文件名与src一致。
  • 变量未定义:若主机未在inventory中设置server_port,可在playbook的vars中提供默认值,或使用default()过滤器。
  • 权限不足:写入/etc/nginx/conf.d需要root权限,已通过become: yes处理。