Ansible 角色使用指南
一、利用角色构造 Ansible Playbook
随着编写的 Playbook 越来越多,会发现很多代码可以复用。例如,一个用于配置 MySQL 数据库的 Play 经过调整后,可以用于另一个应用,只需更改主机名、密码和用户等信息。然而,在实际操作中,Play 可能非常冗长和复杂,包含多个引入的文件、任务和处理程序。直接复制这些代码到另一个 Playbook 中并不高效。
Ansible 提供了一种通用方法,可以更轻松地复用代码:角色(Roles)。角色允许将任务、变量、文件、模板和其他资源打包到一个标准化的目录结构中。只需复制角色目录,即可在不同项目间复用,然后在 Playbook 中调用该角色即可执行。
通过编写良好的角色,可以在调用时传递变量以调整其行为,例如设置主机名、IP 地址、用户名等本地化信息。角色作者还可以为变量设置合理的默认值,以便在未指定时自动使用。
Ansible 角色的优点:
- 易于共享:角色可以分组内容,方便与他人共享代码。
- 定义系统类型:可以编写角色来定义常见系统类型,如 Web 服务器、数据库服务器、Git 仓库等。
- 管理大型项目:角色使大型项目更易于管理。
- 并行开发:不同管理员可以并行开发角色。
除了自己编写和使用角色外,还可以从其他来源获取角色。例如,RHEL 系统角色包含在 rhel-system-roles
软件包中,而社区支持的众多角色可以从 Ansible Galaxy 获取。
二、Ansible 角色结构
Ansible 角色采用标准化的目录结构。顶级目录是角色名称,子目录按用途命名(如 tasks
、handlers
)。以下是角色目录的结构及其用途:
目录名 | 用途说明 |
---|---|
defaults |
main.yml 包含角色变量的默认值,优先级较低,可在 Playbook 中被覆盖。 |
files |
包含角色任务引用的静态文件。 |
handlers |
main.yml 包含角色的处理程序定义(即触发器)。 |
meta |
main.yml 包含角色元信息,如作者、许可证、平台和依赖项。 |
tasks |
main.yml 包含角色的任务定义。 |
templates |
包含角色任务引用的 Jinja2 模板(.j2 文件)。 |
tests |
可包含测试用的清单和 test.yml Playbook。 |
vars |
main.yml 定义角色变量值,优先级较高,通常用于内部用途,不建议在 Playbook 中更改。 |
三、在 Playbook 中使用 Ansible 角色
在 Playbook 中使用角色非常简单。以下是一个基本示例:
---
- name: 测试角色
hosts: node1
roles:
- role1
- role2
对于每个指定的角色,其任务、处理程序、变量和依赖项会按顺序导入到 Playbook 中。角色中的 copy
、script
、template
或 include_tasks
/import_tasks
等任务可以引用角色目录中的文件、模板或任务,无需使用相对或绝对路径。
变量覆盖示例:
创建角色:
cd /etc/ansible/roles ansible-galaxy init cy
在
vars/main.yml
中定义变量:--- a1: 11 a2: 22
在
tasks/main.yml
中编写任务:--- - name: 输出变量 debug: msg: "{{ a1 }}"
在 Playbook 中调用角色并覆盖变量:
--- - name: 测试角色 hosts: node1 roles: - role: cy a1: 333 # 覆盖默认值
执行后,a1
的值将被覆盖为 333
。
四、控制执行顺序
Playbook 中任务的执行顺序如下:
pre_tasks
:在角色之前执行。- 角色任务:按顺序执行每个角色的任务。
- 普通任务:在
tasks
部分定义的任务。 post_tasks
:在所有任务之后执行。
处理程序的执行顺序与任务类似,角色处理程序先执行,然后是 Playbook 中定义的处理程序。
示例:
---
- name: 测试执行顺序
hosts: node1
pre_tasks:
- name: 预任务
shell: echo aaa
notify: 重启服务
roles:
- cy
post_tasks:
- name: 后任务
debug:
msg: "任务完成"
handlers:
- name: 重启服务
debug:
msg: "处理程序被执行"
此外,还可以使用 include_role
(动态包含)或 import_role
(静态导入)在任务中嵌入角色。
五、示例:创建和使用 HTTP 角色
要求:
部署 YUM 仓库。
安装 httpd 软件包。
使用模板生成
/var/www/html/index.html
,内容为:Welcome to HOSTNAME on IPADDRESS
当
index.html
变更时重启 httpd 服务。
步骤:
创建角色:
ansible-galaxy init http
创建模板文件
templates/index.html.j2
:Welcome to {{ ansible_fqdn }} on {{ ansible_ens160.ipv4.address }}
编写任务文件
tasks/main.yml
:--- - name: 配置 BaseOS 仓库 yum_repository: file: server name: baseos description: RHEL8 BaseOS baseurl: file:///mnt/BaseOS enabled: yes gpgcheck: no - name: 配置 AppStream 仓库 yum_repository: file: server name: appstream description: RHEL8 AppStream baseurl: file:///mnt/AppStream enabled: yes gpgcheck: no - name: 挂载光盘 mount: src: /dev/cdrom path: /mnt fstype: iso9660 state: mounted - name: 安装 httpd yum: name: httpd state: present - name: 复制模板文件 template: src: index.html.j2 dest: /var/www/html/index.html notify: 重启 httpd - name: 配置防火墙 firewalld: service: http state: enabled permanent: yes immediate: yes
编写处理程序
handlers/main.yml
:--- - name: 重启 httpd service: name: httpd state: restarted enabled: yes
编写 Playbook
newrole.yml
:--- - name: 配置 Web 服务器 hosts: all roles: - http
执行 Playbook:
ansible-playbook newrole.yml
验证结果:
curl http://node1.example.com
六、系统角色
1. 安装系统角色
yum -y install rhel-system-roles
2. 常用系统角色
角色名 | 用途说明 |
---|---|
rhel-system-roles.kdump |
配置 kdump 崩溃恢复服务 |
rhel-system-roles.network |
配置网络接口 |
rhel-system-roles.selinux |
配置和管理 SELinux |
rhel-system-roles.timesync |
配置时钟同步 |
rhel-system-roles.postfix |
配置 Postfix 邮件传输代理 |
rhel-system-roles.firewall |
配置防火墙 |
rhel-system-roles.tuned |
配置 tuned 服务以优化系统性能 |
3. 示例:使用 timesync 角色
---
- name: 配置时间同步
hosts: all
vars:
timesync_ntp_servers:
- hostname: classroom.example.com
iburst: yes
roles:
- timesync
七、从 Ansible Galaxy 安装角色
1. 安装角色
ansible-galaxy install -r roles/requirements.yml -p /etc/ansible/roles/
2. 管理本地角色
列出已安装角色:
ansible-galaxy list
删除角色:
ansible-galaxy remove role_name
3. 示例 requirements.yml
- name: haproxy
src: file:///root/haproxy.tar.gz
- name: phpinfo
src: file:///root/phpinfo.tar.gz