一、Role 是什么?
Ansible Role(角色) 是一种将 Playbook 模块化、结构化的方式,用于提高自动化脚本的可重用性、可维护性和可移植性。
- 核心思想:把一个完整的 Playbook 拆分成多个逻辑部分(如任务、变量、模板、文件等),并组织成标准目录结构。
- 解决的问题 :
- Playbook 越写越长,难以维护;
- 不同项目之间重复编写相似逻辑;
- 缺乏标准化和共享机制。
✅ 一句话总结:Role = 标准化的 Playbook 组件包,便于跨项目复用。
二、Roles 的目录结构及作用
使用 ansible-galaxy init <role_name> 可以快速生成标准角色目录:
bash
ansible-galaxy init website
生成的目录结构如下:
website/
├── defaults/ # 默认变量(优先级最低)
├── files/ # 静态文件(如 index.html)
├── handlers/ # 触发器(如 restart nginx)
├── meta/ # 元数据(依赖、作者信息等)
├── tasks/ # 主要任务(角色的核心)
├── templates/ # Jinja2 模板文件(如 nginx.conf.j2)
├── tests/ # 测试用例(如何调用该角色)
├── vars/ # 自定义变量(优先级高于 defaults)
└── README.md # 使用说明文档
各目录详解:
| 目录 | 用途 | 示例 |
|---|---|---|
defaults/main.yml |
定义默认变量值 | web_name: nginx |
vars/main.yml |
用户自定义变量(覆盖 defaults) | port: 8080 |
tasks/main.yml |
执行的主要任务列表 | 安装软件、启动服务等 |
handlers/main.yml |
被 notify 触发的任务 | 重启服务 |
templates/*.j2 |
Jinja2 模板文件 | 动态生成配置文件 |
files/ |
静态文件(直接复制) | HTML 页面、证书等 |
meta/main.yml |
角色元信息(依赖、平台支持等) | 依赖其他角色 |
tests/ |
测试 playbook 和 inventory | 如何运行此角色 |
三、实战:开发一个 Nginx Web 网站角色(website)
🎯 需求说明:
- 默认部署
nginx; - 若用户指定其他 Web 服务器(如 httpd),则部署指定服务;
- 若为 nginx,则:
- 监听 ens160 接口 IP 的 8080 端口;
- 在
/usr/share/nginx/html/test.html中写入hello roles。
1. 创建角色
bash
ansible-galaxy init website
2. 编写各组件
✅ defaults/main.yml(默认变量)
yaml
---
web_name: nginx
如果用户未指定
web_name,则默认使用 nginx。
✅ files/test.html
html
hello roles
这是一个静态文件,将被复制到目标主机。
✅ handlers/main.yml
yaml
---
- name: get_status
systemd:
name: nginx
state: restarted
当配置文件变更时,触发此 handler 重启 nginx。
✅ tasks/main.yml(核心任务)
yaml
---
- name: install pkgs for web
yum:
name: "{{ web_name }}"
state: present
- name: start service
service:
name: "{{ web_name }}"
state: started
- name: modify nginx configure file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
when: web_name == "nginx"
notify: get_status
- name: copy file for test.html
copy:
src: test.html
dest: /usr/share/nginx/html/test.html
when: web_name == "nginx"
使用
when条件判断,仅在部署 nginx 时执行特定任务。
✅ templates/nginx.conf.j2
jinja2
...
listen {{ ansible_ens160.ipv4.address }}:8080 default_server;
...
利用 Ansible 自动收集的 facts(如
ansible_ens160.ipv4.address)动态生成监听地址。
💡 注意:确保目标主机有ens160网卡,或根据实际网卡名调整(如ens33)。
3. 调用角色的 Playbook(site.yml)
yaml
---
- hosts: webservers
roles:
- website
或传入变量:
yaml
---
- hosts: webservers
vars:
web_name: httpd
roles:
- website
四、复杂角色的高级用法
1. 拆分 tasks(提高可读性)
当 tasks/main.yml 太长时,可拆分为多个文件:
yaml
# tasks/main.yml
---
- include_tasks: install_pkgs.yml
- include_tasks: start_service.yml
- include_tasks: modify_file.yml
- include_tasks: copy_file.yml
每个子文件只负责一个功能,便于团队协作。
2. 使用 pre_tasks 和 post_tasks
在角色执行前后插入额外任务:
yaml
---
- hosts: node02
pre_tasks:
- name: Ensure nginx is not installed
yum:
name: nginx
state: absent
roles:
- website
post_tasks:
- name: Confirm deployment success
debug:
msg: "website role success"
⚠️ 执行顺序始终为:
pre_tasks→roles→tasks(如果有)→post_tasks
五、使用外部角色
1. 红帽官方角色(RHEL 系统)
bash
yum install rhel-system-roles -y
包含网络、防火墙、内核调优等企业级角色。
2. Ansible Galaxy(社区角色库)
常用命令:
| 命令 | 说明 | 示例 |
|---|---|---|
ansible-galaxy search nginx |
搜索角色 | 查找 nginx 相关角色 |
ansible-galaxy role install geerlingguy.nginx |
安装角色 | 从 Galaxy 下载 |
ansible-galaxy role install geerlingguy.nginx -p ./roles |
指定安装路径 | 存放到当前项目 roles 目录 |
ansible-galaxy role list |
列出已安装角色 | 查看本地有哪些角色 |
ansible-galaxy role info geerlingguy.nginx |
查看角色详情 | 作者、版本、描述等 |
ansible-galaxy role remove geerlingguy.nginx |
卸载角色 | 删除本地角色 |
✅ 最佳实践:将角色安装到项目内的
roles/目录,避免全局污染。
六、Ansible 版本演进简述
| 版本 | 特点 |
|---|---|
| Ansible 2.9 及以前 | 所有模块内置,单体架构 |
| Ansible-core 2.10+ | 拆分为:• ansible-core(核心引擎 + 100+ 基础模块)• Collections(内容集合) :包含模块、插件、角色等完整 Ansible = ansible-core + Collections |
| Ansible Navigator | 在容器中运行 Ansible(开发友好) |
| Red Hat AAP (Ansible Automation Platform) | 企业级平台(原 Tower/AWX) |
🔍 重要提示 :从 Ansible 2.10 开始,很多模块(如
firewalld)不再默认包含,需通过 Collections 安装。
七、角色管理最佳实践
- 命名规范 :使用
作者名.角色名(如geerlingguy.nginx); - 版本控制:通过 Git 管理自研角色;
- 依赖管理 :在
meta/main.yml中声明依赖; - 测试驱动 :利用
tests/目录编写测试用例; - 文档齐全 :
README.md必须包含使用示例。
✅ 练习题(巩固所学)
基础题
- 使用
ansible-galaxy init myweb创建一个新角色。 - 在
defaults/main.yml中设置默认 web 服务为nginx,端口为8080。 - 编写
tasks/main.yml,实现:- 安装指定 web 服务;
- 启动服务;
- 若为 nginx,复制
index.html到网页根目录。
- 创建
templates/nginx.conf.j2,使其监听{``{ ansible_default_ipv4.address }}:{``{ port }}。 - 编写一个 playbook 调用该角色,并传入变量
web_name: httpd。
进阶题
- 将
tasks/main.yml拆分为install.yml、config.yml、start.yml三个文件,并用include_tasks引入。 - 在 playbook 中添加
pre_tasks,确保旧版 nginx 被卸载;添加post_tasks,输出"部署完成"。 - 从 Ansible Galaxy 安装
geerlingguy.docker角色到本地roles/目录,并查看其 README。 - 解释
defaults和vars中同名变量哪个生效?为什么? - 如果目标主机网卡是
eth0而不是ens160,如何让模板自动适配任意网卡 IP?
💡 提示 :第 10 题可使用
ansible_default_ipv4.address(默认路由接口的 IP)或遍历ansible_interfaces动态获取。