当前位置: 首页 > news >正文

Ansible的jinja2 模板、Roles角色详解

目录

  • 一、Jinja2 模板
    • 1.1 在 Ansible 中的使用
    • 1.2 Jinja2 模板语法
      • 1.2.1 基础语法
      • 1.2.2 支持的数据类型
      • 1.2.3 支持的运算
    • 1.3 Jinja2 模板实例
      • 1.3.1 创建模板文件
      • 1.3.2 在 Playbook 中使用模板
      • 1.3.3 效果说明
    • 1.4 流程控制
      • 1.4.1 条件判断
      • 1.4.2 多条件判断
      • 1.4.3 循环
      • 1.4.4 扩展功能
    • 1.5 过滤器
    • 1.6 其他控制结构
    • 1.7 template 模块
      • 1.7.1 copy 与 template 的区别
      • 1.7.2 template 常用参数
      • 1.7.3 使用示例
    • 1.8 Jinja2 使用案例 —— 部署 Redis 服务
      • 1.8.1 背景
      • 1.8.2 本案例涉及的模块/功能
        • 1. 创建 Redis 配置模板
        • 2. 编写 Playbook
  • 二、Roles(角色)
    • 2.1 Roles 的介绍与优势
    • 2.2 Roles 的目录结构
    • 2.3 ansible-galaxy 命令
      • 2.3.1 初始化 Role 目录结构
      • 2.3.2 安装别人写好的 Role
      • 2.3.3 手动下载 Role
      • 2.3.4 总结
  • 三、使用 Roles 部署 Nginx案例
    • 3.1 流程概览(5 步)
    • 3.2 定义任务文件
    • 3.2 定义模板文件
    • 3.3 定义变量
    • 3.4 定义 Handler
    • 3.5 定义调用 Role 的 Playbook
    • 3.6 检查 YAML 文件语法
    • 3.7 执行 Playbook
    • 3.8 查看 Nginx 服务状态

一、Jinja2 模板

Jinja2 是 Python 的全功能模板引擎,在 Python Web 开发中被广泛应用。
在 Ansible 中,Jinja2 模板通常用于动态生成配置文件

1.1 在 Ansible 中的使用

在 Ansible 中,使用 template 模块来处理 Jinja2 模板:

  • template 模块:可以将模板文件渲染后复制到远程主机。
  • copy 模块:只是原封不动地复制文件。

示例对比:

模块功能
copy推送内容原样复制,例如 {{ ansible_fqdn }}不会被替换
template会渲染模板变量,例如 {{ ansible_fqdn }}会被替换为对应主机名

注意:Jinja2 模板中可以使用条件判断和循环,但 playbook 中不允许使用
模板文件通常使用 .j2 后缀。

1.2 Jinja2 模板语法

1.2.1 基础语法

  1. 在 playbook 中使用 template 模块
  2. 模板变量:使用 {{ 变量名 }},例如 {{ PORT }} 或使用 Ansible facts。
  3. 表达式{{ }} 支持 Python 表达式,如:
{{ 3 + 5 }}
{{ 3 in [1,2,3,4,5] }}
- 可以包含比较运算、算术运算、逻辑运算、成员运算等。

1.2.2 支持的数据类型

  • 字符串:单引号或双引号
  • 数字:整数、浮点数
  • 列表[item1, item2, ...]
  • 元组(item1, item2, ...)
  • 字典{key1: value1, key2: value2, ...}
  • 布尔型true / false

1.2.3 支持的运算

  • 算术运算+, -, *, /, //, %, **
  • 比较运算==, !=, >, >=, <, <=
  • 逻辑运算and, or, not

1.3 Jinja2 模板实例

模板通常通过 引用变量 来使用。

1.3.1 创建模板文件

首先,创建一个包含 Jinja2 模板的文件。
在模板中,使用 {{ }} 包裹变量或表达式。

示例:创建 my_template.j2 模板文件

# my_template.j2
ServerName {{ hostname }}
Listen {{ port }}
Debug {{ debug_mode }}

1.3.2 在 Playbook 中使用模板

在 Ansible Playbook 中,可以使用 template 模块 来加载模板文件,并传递变量。

示例:jinja.yml

---
- name: 使用Jinja2模板hosts: your_target_hostsvars:hostname: example.comport: 8080debug_mode: Truetasks:- name: 生成配置文件template:src: my_template.j2dest: /etc/ansible/yml/jinja2/myapp.conf

1.3.3 效果说明

  • 模板文件 (my_template.j2) 定义了变量位置
  • Playbook 通过 vars 传递变量值
  • template 模块 渲染后生成目标配置文件,例如:
ServerName example.com
Listen 8080
Debug True

1.4 流程控制

Jinja2 模板支持流程控制语句:条件判断循环

1.4.1 条件判断

基本格式

{% if EXPR %}执行内容
{% else %}执行内容
{% endif %}

示例

{% if is_production %}# 生产环境配置DebugLevel: 0
{% else %}# 开发/测试环境配置DebugLevel: 2
{% endif %}

1.4.2 多条件判断

格式:

{% if EXPR %}执行内容
{% elif EXPR %}执行内容
{% else %}执行内容
{% endif %}

示例:

{% if env == "production" %}DebugLevel: 0
{% elif env == "staging" %}DebugLevel: 1
{% else %}DebugLevel: 2
{% endif %}

说明:根据变量 env 的值,模板会生成不同配置。

1.4.3 循环

基本格式

{% for i in EXPR %}执行内容
{% endfor %}

示例

{% for item in list_items %}- {{ item }}
{% endfor %}

说明:如果 list_items = ["nginx", "mysql", "redis"],渲染结果为:

- nginx
- mysql
- redis

1.4.4 扩展功能

默认 Jinja2 **不支持 **break** 和 ****continue**
如需启用,可在 /etc/ansible/ansible.cfg 中配置:

jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n,jinja2.ext.loopcontrols

这样即可在循环中使用 breakcontinue 控制流程。

1.5 过滤器

Jinja2 支持 过滤器,用于对变量进行处理。
语法:

{{ variable | filter_name }}

示例

  1. 设置默认值
{{ variable | default("default_value") }}
  1. 获取列表长度
The list has {{ list_items | length }} items.

1.6 其他控制结构

Jinja2 还支持一些高级控制结构:

  • {% include %}:包含其他模板文件
  • {% macro %} / {% call %}:定义和调用宏(类似函数)

注意:Jinja2 功能非常强大,还支持宏、继承、自定义过滤器等。
更多高级用法可参考 Jinja2 官方文档。
在 Ansible 中,可以利用这些模板特性实现灵活的配置文件生成和任务编排。

1.7 template 模块

template 模块和 copy 模块的用法类似,但 template 主要用于渲染 Jinja2 模板

1.7.1 copy 与 template 的区别

模块参数替换用途
copy❌ 不替代变量文件原样复制
template✅ 替代变量生成定制化配置

1.7.2 template 常用参数

参数说明
src指定本地 Jinja2 模板文件路径
dest指定远程主机的目标路径
backup是否备份目标文件,默认 no
mode设置权限
user设置属主用户
group设置属主用户组

1.7.3 使用示例

- name: 部署应用配置hosts: webserverstasks:- name: 渲染并分发配置文件template:src: my_template.j2dest: /etc/myapp/config.confmode: '0644'backup: yes

在不同主机上,模板会自动渲染变量,实现 定制化配置

1.8 Jinja2 使用案例 —— 部署 Redis 服务

1.8.1 背景

Redis 默认只监听 127.0.0.1,其他主机无法访问。
通过 Jinja2 模板结合 Ansible template 模块,可以自定义配置文件,让 Redis 监听指定地址和端口。

1.8.2 本案例涉及的模块/功能

  • Jinja2 模板:动态生成 redis 配置
  • template 模块:渲染模板
  • copy 模块:推送 repo 文件
  • yum 模块:安装/卸载软件包
  • shell 模块:检测 redis 是否安装
  • service 模块:启动/停止/重启服务
  • vars:定义变量
  • register:变量注册
  • ignore_errors:忽略错误
  • tags:任务打标签,方便选择性执行
  • when:条件判断
  • notify / handlers:触发任务(如配置变更后重启 Redis)
1. 创建 Redis 配置模板

文件:redis_conf.j2

# 绑定的IP地址
# {{ ansible_host }} 会替换为当前被控主机的IP,127.0.0.1 表示本地回环
# 这样配置后,Redis 可以同时监听本机和该主机对外的IP
bind {{ ansible_host }} 127.0.0.1# Redis 服务端口,使用变量定义,便于灵活修改
port {{ redis_port }}# 是否启用保护模式(默认yes)。关闭后允许远程访问
protected-mode no# TCP连接队列大小,默认511
tcp-backlog 511# 客户端闲置超时时间(秒)。0 表示不限制
timeout 0# TCP 保活时间(秒),用于检测死连接
tcp-keepalive 300# 是否以守护进程方式运行
daemonize yes# 是否启用 supervisor 管理,no 表示不使用
supervised no# Redis 进程PID文件位置
pidfile /var/run/redis_6379.pid# 日志级别:debug、verbose、notice、warning
# notice 表示一般推荐级别
loglevel notice
  • bind {{ ansible_host }}:动态绑定当前主机 IP
  • port {{ redis_port }}:通过变量定义 Redis 端口
2. 编写 Playbook

文件:redis.yml

---
# Playbook 名称
- name: 部署Redis服务hosts: web              # 目标主机组,需在 inventory 里定义remote_user: root       # 远程执行用户gather_facts: no        # 是否收集被控端的系统信息,这里禁用以加快速度vars:redis_port: 6379      # 定义变量:Redis 服务端口tasks:# ========== 1. 上传 YUM/DNF 仓库文件 ==========- name: Upload base repocopy: src: /etc/yum.repos.d/openEuler.repo   # 控制端本地 repo 文件路径dest: /etc/yum.repos.d/               # 目标主机存放 repo 的目录backup: no                            # 不备份目标文件tags: [upload_yum, upload_repo, redis_server] # 标签,可按需执行此任务# 上传 epel.repo(openEuler 默认可能不需要,可选)- name: Upload epel repo (可选)copy:src: /etc/yum.repos.d/epel.repo       # 控制端本地 EPEL 源文件dest: /etc/yum.repos.d/backup: notags: [upload_epel, upload_repo, redis_server]# ========== 2. 检查 Redis 是否已安装 ==========- name: Check redis installshell: /usr/bin/rpm -q redis            # 执行 rpm 查询命令register: redis_msg                     # 将命令执行结果保存到 redis_msg 变量ignore_errors: yes                      # 即使执行失败也不中断(比如没装 Redis)tags: [check_redis, redis_server]# ========== 3. 安装 Redis ==========- name: Install redis serveryum: name: redis                           # 指定软件包名state: present                        # 确保安装when: redis_msg.failed == true          # 只有检查未安装时才执行tags: [install_redis, redis_server]# ========== 4. 上传 Redis 配置文件 ==========- name: Upload redis.conftemplate:src: redis_conf.j2                    # Jinja2 模板文件dest: /etc/redis.conf                 # 目标配置文件路径notify: Restart Redis                   # 配置更新后通知 handlers 执行“Restart Redis”tags: [upload_redis.conf, redis_server]# ========== 5. 启动 Redis 服务并设置开机自启 ==========- name: Start Redis serverservice:name: redis                           # 服务名(openEuler 默认是 redis)state: started                        # 确保服务已启动enabled: yes                          # 设置开机自启tags: [start_redis, redis_server]# ========== 6. 手动重启 Redis ==========- name: Restart Redis serverservice:name: redisstate: restarted                      # 强制重启tags: [restart_redis]# ========== 7. 停止 Redis ==========- name: Stop Redis Serverservice: name: redisstate: stopped                        # 停止服务tags: [stop_redis, uninstall_redis]# ========== 8. 卸载 Redis ==========- name: Uninstall Redis Serveryum: name: redisstate: absent                         # 确保 Redis 被卸载tags: [uninstall_redis]# ========== handlers:处理程序 ==========handlers:- name: Restart Redisservice:name: redisstate: restarted                      # 当配置文件更新时自动触发服务重启

输出

[root@ansible-manager j2]# ansible-playbook redis.yml --syntax-checkplaybook: redis.yml
[root@ansible-manager j2]# ansible-playbook redis.yml --list-tasksplaybook: redis.ymlplay #1 (web_group): 部署Redis服务	TAGS: []tasks:Upload yum repo	TAGS: [redis_server, upload_repo, upload_yum]Upload epel repo	TAGS: [redis_server, upload_epel, upload_repo]Check redis install	TAGS: [check_redis, redis_server]Install redis server	TAGS: [install_redis, redis_server]Upload redis.conf	TAGS: [redis_server, upload_redis.conf]Start Redis server	TAGS: [redis_server, start_redis]Restart Redis server	TAGS: [restart_redis]Stop Redis Server	TAGS: [stop_redis, uninstall_redis]Uninstall Redis Server	TAGS: [uninstall_redis]
[root@ansible-manager j2]# ansible-playbook redis.yml --list-tagsplaybook: redis.ymlplay #1 (web_group): 部署Redis服务	TAGS: []TASK TAGS: [check_redis, install_redis, redis_server, restart_redis, start_redis, stop_redis, uninstall_redis, upload_epel, upload_redis.conf, upload_repo, upload_yum]
[root@ansible-manager j2]# ansible-playbook redis.yml PLAY [部署Redis服务] **********************************************************************************************************************************************************TASK [Upload yum repo] ****************************************************************************************************************************************************
[WARNING]: Platform linux on host 10.0.0.11 is using the discovered Python interpreter at /usr/bin/python3, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [10.0.0.11]
[WARNING]: Platform linux on host 10.0.0.13 is using the discovered Python interpreter at /usr/bin/python3, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [10.0.0.13]
[WARNING]: Platform linux on host 10.0.0.12 is using the discovered Python interpreter at /usr/bin/python3, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [10.0.0.12]# "stdout": "package redis is not installed"     没有被安装,说明之前没有安装过
TASK [Check redis install] ************************************************************************************************************************************************
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.  If you need to use command because yum, dnf or zypper is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
fatal: [10.0.0.13]: FAILED! => {"changed": true, "cmd": "/usr/bin/rpm -q redis", "delta": "0:00:00.006004", "end": "2025-09-13 16:47:06.386991", "msg": "non-zero return code", "rc": 1, "start": "2025-09-13 16:47:06.380987", "stderr": "", "stderr_lines": [], "stdout": "package redis is not installed", "stdout_lines": ["package redis is not installed"]}
...ignoring
fatal: [10.0.0.11]: FAILED! => {"changed": true, "cmd": "/usr/bin/rpm -q redis", "delta": "0:00:00.007042", "end": "2025-09-13 16:47:06.398061", "msg": "non-zero return code", "rc": 1, "start": "2025-09-13 16:47:06.391019", "stderr": "", "stderr_lines": [], "stdout": "package redis is not installed", "stdout_lines": ["package redis is not installed"]}
...ignoring
fatal: [10.0.0.12]: FAILED! => {"changed": true, "cmd": "/usr/bin/rpm -q redis", "delta": "0:00:00.006628", "end": "2025-09-13 16:47:06.404864", "msg": "non-zero return code", "rc": 1, "start": "2025-09-13 16:47:06.398236", "stderr": "", "stderr_lines": [], "stdout": "package redis is not installed", "stdout_lines": ["package redis is not installed"]}
...ignoringTASK [Install redis server] ***********************************************************************************************************************************************
changed: [10.0.0.13]
changed: [10.0.0.12]
changed: [10.0.0.11]TASK [Upload redis.conf] **************************************************************************************************************************************************
changed: [10.0.0.13]
changed: [10.0.0.11]
changed: [10.0.0.12]TASK [Start Redis server] *************************************************************************************************************************************************
changed: [10.0.0.12]
changed: [10.0.0.13]
changed: [10.0.0.11]TASK [Restart Redis server] ***********************************************************************************************************************************************
changed: [10.0.0.13]
changed: [10.0.0.11]
changed: [10.0.0.12]TASK [Stop Redis Server] **************************************************************************************************************************************************
changed: [10.0.0.13]
changed: [10.0.0.11]
changed: [10.0.0.12]TASK [Uninstall Redis Server] *********************************************************************************************************************************************
changed: [10.0.0.11]
changed: [10.0.0.13]
changed: [10.0.0.12]# 上面redis已经被卸载,
# 所以 提示""msg": "Could not find the requested service"没有发现该服务
RUNNING HANDLER [Restart Redis] *******************************************************************************************************************************************
fatal: [10.0.0.12]: FAILED! => {"changed": false, "msg": "Could not find the requested service redis: host"}
fatal: [10.0.0.13]: FAILED! => {"changed": false, "msg": "Could not find the requested service redis: host"}
fatal: [10.0.0.11]: FAILED! => {"changed": false, "msg": "Could not find the requested service redis: host"}NO MORE HOSTS LEFT ********************************************************************************************************************************************************PLAY RECAP ****************************************************************************************************************************************************************
10.0.0.11                  : ok=8    changed=7    unreachable=0    failed=1    skipped=0    rescued=0    ignored=1   
10.0.0.12                  : ok=8    changed=7    unreachable=0    failed=1    skipped=0    rescued=0    ignored=1   
10.0.0.13                  : ok=8    changed=7    unreachable=0    failed=1    skipped=0    rescued=0    ignored=1 

二、Roles(角色)

在 Ansible 中,Roles 是一种规范化机制,用于将复杂的 Playbook 分解为多个可复用、结构化的部分,从而简化 Playbook 的编写和维护。

建议:每个 Role 最好只包含一个 tasks,方便调用并实现良好的解耦。

2.1 Roles 的介绍与优势

  1. 目录位置
    • 默认写在 /etc/ansible/roles
    • 也可以写在其他路径,但需要手动创建 roles 文件夹。
  2. 问题与解决
    • 如果不使用 Role,同时部署 webdatabasekeepalived 等不同服务,或者在不同服务器组合不同应用,就需要写多个 Playbook 文件,维护困难。
    • Roles 通过层次化、结构化组织 Playbook,使得变量、任务和处理器可以自动装载,便于复用。
  3. 核心概念
    • Role 将 Playbook 的不同内容分离为独立目录:
      • 变量(vars)
      • 文件(files)
      • 模板(templates)
      • 任务(tasks)
      • 处理器(handlers)
      • 模块(modules,可选)
      • 元信息(meta)
    • 使用 Role 时,只需在 Playbook 中通过 include_roleroles: 指令调用即可。
  4. 应用场景
    • 基于主机构建服务(如部署 web 服务、数据库等)。
    • 构建守护进程或其他系统服务。

2.2 Roles 的目录结构

创建一个示例 Role 目录:

mkdir -pv /etc/ansible/roles/{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
  • 说明:
    • {nginx,mysql,httpd}:Role 名称,可根据实际服务命名。
    • files/:存放静态文件。
    • templates/:存放 Jinja2 模板。
    • vars/:存放变量文件。
    • tasks/:存放任务文件(main.yml)。
    • handlers/:存放处理器文件(main.yml)。
    • meta/:存放 Role 元信息。
    • default/:存放默认变量文件(main.yml)。

Role 的目录结构决定了 Ansible 自动查找变量、任务、处理器等文件的方式,使 Playbook 更加模块化和可复用。

yum install -y tree[root@ansible-manager j2]# tree /etc/ansible/roles
/etc/ansible/roles
├── httpd                      # Role 名称:用于部署或管理 httpd 服务
│   ├── default                # 默认变量目录(main.yml),用于定义 Role 的默认值
│   ├── files                  # 存放静态文件,如配置文件、二进制文件等,供 tasks 调用 copy 模块使用
│   ├── handlers               # 存放处理器文件(main.yml),如服务重启、刷新配置等操作
│   ├── meta                   # 存放 Role 元信息,如依赖的其他 Role、作者信息、最小 Ansible 版本等
│   ├── tasks                  # 存放任务文件(main.yml),定义该 Role 的具体操作步骤
│   ├── templates              # 存放 Jinja2 模板文件,用于生成动态配置文件
│   └── vars                   # 存放变量文件(main.yml),用于定义强制变量或特定环境变量
├── mysql                      # Role 名称:用于部署或管理 MySQL 服务
│   ├── default                # 默认变量目录(main.yml)
│   ├── files                  # 静态文件目录
│   ├── handlers               # 处理器目录
│   ├── meta                   # Role 元信息目录
│   ├── tasks                  # 任务目录
│   ├── templates              # Jinja2 模板目录
│   └── vars                   # 变量目录
└── nginx                      # Role 名称:用于部署或管理 Nginx 服务├── default                # 默认变量目录(main.yml)├── files                  # 静态文件目录├── handlers               # 处理器目录├── meta                   # Role 元信息目录├── tasks                  # 任务目录├── templates              # Jinja2 模板目录└── vars                   # 变量目录

2.3 ansible-galaxy 命令

ansible-galaxy 是 Ansible 提供的 Role 管理工具,用于:

  1. 初始化 Role 目录结构;
  2. 下载或安装 Galaxy 上别人写好的 Role;
  3. 管理已有 Role。

2.3.1 初始化 Role 目录结构

使用 ansible-galaxy init 创建一个 Role 的标准目录:

# 初始化 Role 目录
[root@ansible-manager ~]# ansible-galaxy init /etc/ansible/roles/webserver
# 执行后,输出
- Role /etc/ansible/roles/webserver was created successfully
  • 会在 /etc/ansible/roles/webserver 下创建完整目录结构:
[root@ansible-manager ~]# tree /etc/ansible/roles/webserver
/etc/ansible/roles/webserver
├── defaults
│   └── main.yml             # 默认变量文件# 用于定义 Role 的默认变量# 优先级低,会被 vars/main.yml 或 Playbook 中变量覆盖
├── files                    # 静态文件目录# 存放 Role 中需要复制到目标主机的文件# 任务中可通过 copy: 模块引用
├── handlers
│   └── main.yml             # 处理器文件# 用于定义触发操作,如服务重启、刷新配置# Playbook 或 tasks 中通过 notify 调用
├── meta
│   └── main.yml             # Role 元信息文件# 可定义角色依赖、作者信息、许可证、最低 Ansible 版本# 例如:# dependencies:#   - common
├── README.md                # Role 说明文件# 介绍 Role 功能、使用方法、变量说明等
├── tasks
│   └── main.yml             # Role 的主要任务文件# 定义该 Role 的执行步骤# 可 include 或 import 其他任务文件实现模块化
├── templates                # 模板文件目录# 存放 Jinja2 模板,用于动态生成配置文件# 任务中通过 template: 模块引用
├── tests
│   ├── inventory            # 测试主机清单文件
│   └── test.yml             # 测试 Playbook 文件# 用于在本地或测试环境验证 Role 是否正确执行
└── vars└── main.yml             # 强制变量文件# 优先级高于 defaults/main.yml# 用于定义必须的变量或特定环境变量,确保 Role 正常运行
  • 这样你就可以直接在 Role 里写任务、变量和模板。

2.3.2 安装别人写好的 Role

可以从 Galaxy 下载别人已经写好的 Role,例如 MySQL:

ansible-galaxy role install -p /etc/ansible/roles tenequm.mysql
  • -p /etc/ansible/roles:指定 Role 安装路径。
  • tenequm.mysql:Galaxy 上的 Role 名称。

可能遇到的问题

[ERROR]: failed to download the file: <urlopen error timed out>
[WARNING]: - tenequm.mysql was NOT installed successfully.
  • 原因:网络超时或 Galaxy 仓库访问失败。

2.3.3 手动下载 Role

当自动下载失败时,可以使用 wget 手动拉取:

# 下载 Role 压缩包
wget https://github.com/tenequm/ansible-mysql/archive/1.0.1.tar.gz# 解压
tar xf 1.0.1.tar.gz[root@ansible-manager roles]# tree ansible-mysql-1.0.1
ansible-mysql-1.0.1
├── defaults
│   └── main.yml             # 默认变量文件# 用于定义 Role 的默认变量,如 MySQL 端口、用户名、密码等# 优先级低,会被 vars/main.yml 或 Playbook 中的变量覆盖
├── LICENSE                  # 授权许可文件# 说明 Role 的版权信息和使用许可
├── meta
│   └── main.yml             # Role 元信息文件# 定义角色的依赖关系、作者信息、最小 Ansible 版本等# 例如:# dependencies:#   - common
├── README.md                # Role 说明文件# 描述 Role 功能、安装方法、变量说明、使用示例等
├── tasks
│   └── main.yml             # 主要任务文件# 定义 Role 执行步骤,如安装 MySQL、初始化数据库、配置服务等# 可以 include 或 import 其他任务文件实现模块化
├── templates
│   └── my.cnf.j2            # Jinja2 模板文件# 用于动态生成 MySQL 配置文件# 可通过 `template:` 模块将配置渲染到目标主机
├── tests
│   ├── README.MD            # 测试说明文件# 描述如何在测试环境验证该 Role
│   └── test.yml             # 测试 Playbook 文件# 用于快速验证 Role 是否能够在目标主机正确执行# 列出已安装的 Roles
[root@ansible-manager roles]# ansible-galaxy list
# /etc/ansible/roles
- ansible-mysql-1.0.1, (unknown version)
- webserver, (unknown version)# 查看指定 Role 信息
[root@ansible-manager roles]# ansible-galaxy info tenequm.mysqlRole: tenequm.mysqldescription: Simply installs MySQL 5.7 on Xenial.commit: b3a7139ba44a91e9568345565e861e326e9d401ecommit_message: Added priveleges configs for users.created: 2023-05-08T20:18:24.338543Zdownload_count: 351github_branch: mastergithub_repo: ansible-mysqlgithub_user: tenequmid: 103imported: 2017-06-08T21:57:26.659770-04:00modified: 2023-10-10T00:48:33.420438Zpath: ('/root/.ansible/roles', '/usr/share/ansible/roles', '/etc/ansible/roles')upstream_id: 17029username: tenequm
  • 解压后会生成目录:ansible-mysql-1.0.1
  • 该目录下包含完整 Role 结构(tasks、handlers、vars、templates 等)。
  • 将解压后的目录移动到 /etc/ansible/roles/ 即可使用。

2.3.4 总结

  • ansible-galaxy init:创建 Role 目录结构,适合自定义开发 Role。
  • ansible-galaxy role install:从 Galaxy 下载 Role,但可能受网络限制。
  • 手动下载 + 解压:解决下载超时或网络问题。
  • Role 下载完成后,可以直接在 Playbook 中通过 roles:include_role: 调用使用。

三、使用 Roles 部署 Nginx案例

3.1 流程概览(5 步)

  1. 定义任务文件(tasks)
  2. 定义模板文件(templates)生成配置文件
  3. 定义变量(vars)
  4. 定义触发器(handlers)
  5. 定义 Playbook 调用 Role(roles.yml)

然后执行以下操作:

  • 检查 YAML 语法
  • 执行 roles.yml 文件
  • 查看 Nginx 服务状态

创建目录

mkdir -p /etc/ansible/roles/nginx/
mkdir -p /etc/ansible/roles/nginx/tasks
mkdir -p /etc/ansible/roles/nginx/templates
mkdir -p /etc/ansible/roles/nginx/vars
mkdir -p /etc/ansible/roles/nginx/handlers
mkdir  -p /etc/ansible/roles/nginx/files

3.2 定义任务文件

文件路径:/etc/ansible/roles/nginx/tasks/main.yml

vim /etc/ansible/roles/nginx/tasks/main.yml
# 任务1:安装 wget 工具
- name: install wgetyum:name: wget           # 安装的软件包名称state: present       # 确保软件包已经安装(如果已安装则跳过)# 任务2:安装 Nginx 安装包
- name: copy nginx rpm package to remote hostcopy:src: /etc/ansible/roles/nginx/files/nginx-1.18.0-1.el7.ngx.x86_64.rpm   # 本地文件在 playbook 运行机器的路径dest: /tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm  # 目标主机上的路径mode: '0644'# 使用 shell 命令下载指定版本的 Nginx rpm 包# -O 指定保存路径为 roles 文件夹下的 files 目录# 注意:使用 command 模块,不会经过 shell,因此不能使用管道或重定向符号# 任务3:复制 Nginx rpm 包到目标路径
- name: cp nginxcopy:src: nginx-1.18.0-1.el7.ngx.x86_64.rpm  # 源文件路径(相对于 tasks 执行路径,通常指 roles/files)dest: /tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm  # 复制到目标主机的 /tmp 目录# 任务4:安装 Nginx
- name: install nginxyum:name: /tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm  # 指定 rpm 包路径进行安装state: latest       # 确保安装最新版本,如果已安装相同版本则跳过# 任务5:生成 Nginx 配置文件
- name: conftemplate:src: nginx.conf.j2  # 源模板文件(Jinja2 模板)dest: /etc/nginx/nginx.conf  # 渲染后生成的目标配置文件路径tags: nginxconf        # 任务标签,可在执行 playbook 时按标签筛选执行notify: new conf to reload  # 当模板文件发生变化时触发 handler:重新加载 Nginx 服务# 任务6:启动并设置 Nginx 服务开机自启
- name: start serviceservice:name: nginx       # 服务名称state: started    # 确保服务已经启动enabled: true     # 设置服务开机自启

注:使用 template 模块动态生成配置文件,并通过 notify 调用 handler。

3.2 定义模板文件

文件路径:/etc/ansible/roles/nginx/templates/nginx.conf.j2

关键配置示例:

vim /etc/ansible/roles/nginx/templates/nginx.conf.j2
# 设置 Nginx 运行的系统用户
user  nginx;# 设置工作进程数,使用 Jinja2 变量 {{ ansible_processor_vcpus }} 自动获取目标主机 CPU 核心数
worker_processes  {{ ansible_processor_vcpus }};# 错误日志路径及日志级别
error_log  /var/log/nginx/error.log warn;# nginx 主进程 PID 文件路径
pid        /var/run/nginx.pid;# 事件驱动模块配置
events {# 每个 worker 进程允许的最大连接数worker_connections  1024;
}# HTTP 模块配置
http {# 引入 MIME 类型映射文件include       /etc/nginx/mime.types;# 默认内容类型default_type  application/octet-stream;# 定义日志格式 mainlog_format  main  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';# 访问日志路径和使用的日志格式access_log  /var/log/nginx/access.log  main;# 高效文件传输开关sendfile        on;# 客户端与服务端的连接保持时间,单位:秒keepalive_timeout  65;# 定义 HTTP 服务中的 server 块server {# 监听端口,使用 Jinja2 变量 {{ nginxport }},可以在 vars 中自定义listen       {{ nginxport }};# 服务名称或主机名server_name  localhost;# location 配置location / {# 网站根目录root   /usr/share/nginx/html;# 默认首页index  index.html index.htm;}# 错误页面配置error_page   500 502 503 504  /50x.html;# 单独指定错误页面路径location = /50x.html {root   /usr/share/nginx/html;}}# 引入 conf.d 目录下的所有额外配置文件include /etc/nginx/conf.d/*.conf;
}

使用 Jinja2 变量 {{ nginxport }} 动态生成监听端口。

3.3 定义变量

文件路径:/etc/ansible/roles/nginx/vars/main.yml

vim /etc/ansible/roles/nginx/vars/main.yml
nginxport: 9999

可以在 Playbook 中覆盖。

3.4 定义 Handler

文件路径:/etc/ansible/roles/nginx/handlers/main.yml

vim /etc/ansible/roles/nginx/handlers/main.yml
- name: new conf to reloadservice:name: nginxstate: restarted

当模板文件更新时,通过 notify 自动触发 Nginx 重启。

3.5 定义调用 Role 的 Playbook

文件路径:/etc/ansible/roles/nginx/roles.yml

vim /etc/ansible/roles/nginx/roles.yml
- hosts: webremote_user: rootroles:- nginx

3.6 检查 YAML 文件语法

ansible-playbook --syntax-check roles.yml

会自动检查 Role 内所有 yml 文件语法。

3.7 执行 Playbook

ansible-playbook roles.yml

3.8 查看 Nginx 服务状态

systemctl status nginx

确认 Nginx 已经启动,并监听指定端口。


文章转载自:

http://LZJ7hOOA.phcqk.cn
http://YvVjVJXW.phcqk.cn
http://o79xac0q.phcqk.cn
http://qtV9Aw2C.phcqk.cn
http://BlZDdVY5.phcqk.cn
http://DMqxFuT2.phcqk.cn
http://CHAEMHqU.phcqk.cn
http://G1QoKqlQ.phcqk.cn
http://yhxMUmD6.phcqk.cn
http://OFhdQLYV.phcqk.cn
http://0rgHOgVe.phcqk.cn
http://T5SeNGGn.phcqk.cn
http://l2z8aFyr.phcqk.cn
http://JbVN1QWt.phcqk.cn
http://fvMUGm3N.phcqk.cn
http://TIaYCkfV.phcqk.cn
http://ZObSXxcg.phcqk.cn
http://UZcqVPX4.phcqk.cn
http://rxuNrRKg.phcqk.cn
http://x5NrjNmK.phcqk.cn
http://BCjscEuC.phcqk.cn
http://BfOUIYee.phcqk.cn
http://np2cpH0s.phcqk.cn
http://G9ecM6Cn.phcqk.cn
http://Xuxtk8W4.phcqk.cn
http://x9EPJFDr.phcqk.cn
http://X1QdYCwH.phcqk.cn
http://xiFsehbS.phcqk.cn
http://fglEkxkv.phcqk.cn
http://iMwA1SIz.phcqk.cn
http://www.dtcms.com/a/382169.html

相关文章:

  • Linux内核的PER_CPU机制
  • 树莓派组建nas,云服务器及家庭影院
  • 二叉树hot100-中等
  • MX 模拟赛二总结
  • windows rocketmq 启动时报 java.lang.NullPointerException
  • 文本处理三剑客——grep、sed、awk
  • o2oa待办流程和已办流程表
  • 【WebSocket✨】入门之旅(三):WebSocket 的实战应用
  • 闪电科创-交通信号灯仿真SUMO
  • 【自动化】深入浅出UIAutomationClient:C#桌面自动化实战指南
  • 自定义类型:结构体、联合与枚举(1)
  • 在 Ubuntu 系统中基于 Miniconda 安装 VLLM 并启动模型 + Dify 集成指南
  • JavaWeb--day4--WebHttp协议Tomcat
  • Linux命令行的核心理念与实用指南(进阶版)
  • 机器学习-模型验证
  • 3-机器学习与大模型开发数学教程-第0章 预备知识-0-3 函数初步(多项式、指数、对数、三角函数、反函数)
  • 使用Aop和自定义注解实现SpringTask定时任务中加锁逻辑的封装
  • 远程依赖管理新范式:cpolar赋能Nexus全球协作
  • 【个人项目】【前端实用工具】OpenAPI to TypeScript 转换器
  • 贪心算法应用:物流装箱问题详解
  • 《用 TensorFlow 构建回归模型:从零开始的预测之路》
  • charles功能
  • Ceph OSD 元数据信息
  • Stanford CS336 | Assignment 2 - FlashAttention-v2 Pytorch Triotn实现
  • 【Docker】容器
  • C++ 类型推导(第一部分)
  • 联邦学习模型完成之后在验证集上面,如何判断输出正确与否
  • 优选算法---链表
  • 从理据到算法:认知语义学象似性对人工智能深层语义分析的重塑与前瞻
  • 39.网络流入门