Ansible 角色管理指南
实验环境设置
以下命令用于准备实验环境,创建一个工作目录并配置基本的Ansible设置:
# 创建web工作目录并进入
[azurewhisky@controller ~]$ mkdir web && cd web
# 创建Ansible配置文件
[azurewhisky@controller web]$ cat > ansible.cfg <<'EOF'
[defaults]
remote_user = azurewhisky # 设置远程登录用户名
inventory = ./inventory # 指定清单文件位置
[privilege_escalation]
become = True # 启用权限提升
become_user = root # 提升到root用户
become_method = sudo # 使用sudo方法
become_ask_pass = False # 不询问密码
EOF
# 创建主机清单文件
[azurewhisky@controller web]$ cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF
Ansible 角色详解
什么是Ansible角色?
在实际生产环境中,Playbook往往会变得很长且复杂,包含许多文件、任务和处理程序。随着编写的Playbook越来越多,我们会发现有很多机会可以复用之前编写的代码。
Ansible角色提供了一种标准化方式来打包和复用自动化代码。它将任务、变量、文件、模板等资源组织在一个标准化的目录结构中,只需将角色从一个项目复制到另一个项目,然后在Playbook中调用即可。
Ansible角色结构
通过以下命令可以初始化一个标准的Ansible角色:
[azurewhisky@controller web]$ ansible-galaxy init azurewhisky
- azurewhisky was created successfully
# 查看角色目录结构
[azurewhisky@controller web]$ tree azurewhisky
azurewhisky
├── defaults # 默认变量目录(低优先级)
│ └── main.yml
├── files # 静态文件目录
├── handlers # 处理程序目录
│ └── main.yml
├── meta # 元数据目录
│ └── main.yml
├── README.md # 角色说明文档
├── tasks # 任务目录
│ └── main.yml
├── templates # 模板目录
├── tests # 测试目录
│ ├── inventory
│ └── test.yml
└── vars # 变量目录(高优先级)
└── main.yml
8 directories, 8 files
各目录用途说明:
- defaults:包含角色变量的默认值(低优先级,易被覆盖)
- files:存放角色任务引用的静态文件
- handlers:包含角色的处理程序定义
- meta:包含角色元信息(作者、许可证、依赖等)
- tasks:包含角色的主要任务定义
- templates:存放Jinja2模板文件
- tests:包含测试用的清单和Playbook
- vars:定义角色变量(高优先级,用于内部功能)
- README.md:角色使用说明文档
角色存放位置
Ansible默认在以下位置查找角色:
~/.ansible/roles
/usr/share/ansible/roles
/etc/ansible/roles
优先级从上到下递减。可以通过配置文件自定义角色路径:
# 在ansible.cfg中设置角色路径
[defaults]
roles_path = ./roles # 相对路径示例
# 多个路径用冒号分隔
roles_path = /etc/ansible/roles:/home/azurewhisky/web/roles
创建自定义角色
下面创建一个Apache Web服务器角色的完整示例:
# 创建角色目录并初始化Apache角色
[azurewhisky@controller web]$ mkdir roles
[azurewhisky@controller web]$ ansible-galaxy init apache --init-path=./roles
配置任务文件
# roles/apache/tasks/main.yml
---
# Apache角色任务文件
- name: 安装Web服务器
yum:
name: "{{ web_package }}" # 使用变量指定软件包名
state: latest
- name: "启动{{ web_service }}服务"
service:
name: "{{ web_service }}" # 使用变量指定服务名
state: started
enabled: yes # 设置开机自启
- name: 配置登录提示信息
template:
src: motd.j2 # 源模板文件
dest: /etc/motd # 目标文件位置
- name: 配置AzureWhisky站点
template:
src: azurewhisky.conf.j2 # 虚拟主机配置模板
dest: /etc/httpd/conf.d/azurewhisky.conf
notify:
- 重启Web服务 # 触发处理程序
- name: 创建网站根目录
file:
path: "/var/www/html/{{ ansible_hostname }}" # 使用主机名创建目录
state: directory
- name: 创建首页文件
template:
src: index.html.j2 # 首页模板
dest: "/var/www/html/{{ ansible_hostname }}/index.html"
配置默认变量
# roles/apache/defaults/main.yml
---
# Apache角色默认变量
web_package: httpd # Web服务器软件包名
web_service: httpd # Web服务名称
创建模板文件
{# roles/apache/templates/motd.j2 #}
hello guys!
Welcome to {{ ansible_fqdn }}! {# 使用事实变量填充完全限定域名 #}
{# roles/apache/templates/azurewhisky.conf.j2 #}
# {{ ansible_managed }} {# Ansible管理标记 #}
<VirtualHost *:80>
ServerAdmin azurewhisky@{{ ansible_fqdn }}
ServerName {{ ansible_fqdn }}
ErrorLog logs/{{ ansible_hostname }}-error.log
CustomLog logs/{{ ansible_hostname }}-common.log common
DocumentRoot /var/www/html/{{ ansible_hostname }}/
<Directory /var/www/html/{{ ansible_hostname }}/>
Options +Indexes +FollowSymlinks +Includes
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
配置处理程序
# roles/apache/handlers/main.yml
---
# Apache角色处理程序
- name: 重启Web服务
service:
name: "{{ web_service }}"
state: restarted
创建首页模板
{# roles/apache/templates/index.html.j2 #}
Welcome to {{ ansible_fqdn }} !
配置角色元数据
---
galaxy_info:
author: azurewhisky
description: azurewhisky的Web服务器角色
company: azurewhisky世界
license: GPLv2
min_ansible_version: 2.4
platforms:
- name: Fedora
versions:
- all
- 25
galaxy_tags: [apache, web] # 角色标签
dependencies: [] # 角色依赖项
调用角色
在Playbook中调用角色非常简单:
# 基本调用方式
---
- name: 部署Apache
hosts: node1
roles:
- apache # 直接引用角色名
# 带参数调用方式
---
- name: 部署Apache
hosts: node1
roles:
- role: apache # 明确指定角色
web_package: httpd # 传递参数
web_service: httpd
- { role: apache, web_package: httpd, web_service: httpd } # 简写格式
执行Playbook并验证结果:
# 验证motd配置
[azurewhisky@controller web]$ ssh root@node1
hello guys!
Welcome to node1.lab.example.com!
# 验证网站访问
[root@node1 ~]$ curl http://node1/
Welcome to node1.azurewhisky.top !
角色依赖关系
角色可以声明依赖其他角色,例如Web服务器角色可能依赖防火墙角色:
# roles/apache/meta/main.yml
dependencies:
- role: firewall
service: http # 传递参数给依赖角色
创建防火墙角色:
[azurewhisky@controller web]$ ansible-galaxy init firewall --init-path=./roles
配置防火墙角色任务:
# roles/firewall/tasks/main.yml
---
# 防火墙角色任务
- name: 安装firewalld
yum:
name: firewalld
state: latest
- name: 启动并启用firewalld服务
service:
name: firewalld
state: started
enabled: true
- name: 配置防火墙服务
firewalld:
state: enabled # 启用规则
immediate: true # 立即生效
permanent: true # 永久生效
service: "{{ service }}" # 使用变量指定服务
配置防火墙默认变量:
# roles/firewall/defaults/main.yml
---
# 防火墙默认变量
service: ssh # 默认允许SSH服务
任务执行顺序
Ansible按照特定顺序执行任务:
pre_tasks
- 前置任务roles
- 角色任务tasks
- 普通任务post_tasks
- 后置任务
注意:剧本中的书写顺序不影响实际执行顺序。
示例演示:
---
- name: 测试任务执行顺序
hosts: node1
gather_facts: false # 禁用事实收集
pre_tasks:
- name: 前置任务
shell: echo '这是前置任务'
roles:
- test_task_exec_order # 调用测试角色
tasks:
- name: 普通任务
shell: echo '这是普通任务'
post_tasks:
- name: 后置任务
shell: echo '这是后置任务'
处理程序执行顺序
处理程序按照以下顺序执行:
- pre_tasks通知的处理程序
- roles任务
- roles通知的处理程序
- tasks任务
- tasks通知的处理程序
- post_tasks任务
- post_tasks通知的处理程序
重要:剧本中的处理程序具有全局作用域,可以被任何任务通知。
动态角色调用
使用include_role
和import_role
在任务中动态调用角色:
---
- hosts: node1
tasks:
- shell: echo '第一个任务'
- name: 在任务中调用角色
import_role: # 或使用include_role
name: hello
when: condition_met # 条件判断
区别说明:
import_role
:执行前解析角色,语法错误会立即终止include_role
:执行时解析角色,条件为false时不解析
Ansible角色的优势
- 标准化:为系统类型(Web服务器、数据库等)定义标准配置
- 并行开发:多个管理员可以同时开发不同角色
- 代码复用:轻松共享和复用自动化代码
- 易于管理:使大型项目更易于维护和组织
角色开发最佳实践
- 避免敏感信息:不要将密码或密钥存储在角色中,使用变量参数化
- 精简结构:使用
ansible-galaxy init
创建角色,删除不需要的目录 - 完善文档:维护README.md和meta/main.yml文件说明角色用途
- 功能专注:每个角色应专注于特定功能,避免过于复杂
- 代码重构:经常重用和重构角色,避免为边缘情况创建新角色
- 版本控制:使用版本控制系统管理角色演变
使用系统角色
系统角色介绍
RHEL从7.4开始提供预打包的系统角色,这些角色可以帮助标准化RHEL主机的配置。例如,使用timesync角色可以统一配置RHEL6和7的时间同步,无需关心底层是ntpd还是chronyd服务。
安装系统角色
[azurewhisky@controller ~]$ sudo yum install -y rhel-system-roles
# 系统角色安装在标准位置
[azurewhisky@controller ~]$ ls -1 /usr/share/ansible/roles/
# 文档位于
[azurewhisky@controller ~]$ ls /usr/share/doc/rhel-system-roles
时间同步角色示例
---
- name: 时间同步配置
hosts: node1
vars:
timesync_ntp_servers:
- hostname: classroom.example.com
iburst: yes # 启用快速初始同步
timezone: "Asia/Shanghai" # 设置时区
roles:
- rhel-system-roles.timesync # 调用系统角色
tasks:
- name: 设置时区
timezone:
name: "{{ timezone }}"
SELinux角色示例
---
- name: SELinux配置
hosts: node1
vars:
selinux_state: enforcing # 设置强制模式
selinux_booleans:
- name: 'httpd_enable_homedirs'
state: 'on'
persistent: 'yes' # 永久生效
selinux_fcontexts:
- target: '/srv/www(/.*)?'
setype: 'httpd_sys_content_t'
state: 'present'
roles:
- rhel-system-roles.selinux
处理需要重启的SELinux配置
---
- hosts: node1,node2
vars:
selinux_state: enforcing
tasks:
- block: # 块错误处理
- name: 应用SELinux角色
include_role:
name: rhel-system-roles.selinux
rescue: # 救援块
- name: 检查是否需要重启以外的错误
fail:
when: not selinux_reboot_required
- name: 重启受管主机
reboot:
- name: 重新应用SELinux角色
include_role:
name: rhel-system-roles.selinux
使用Ansible Galaxy部署角色
Ansible Galaxy介绍
Ansible Galaxy是一个由社区维护的角色仓库,包含大量可重用的角色,帮助用户快速实现自动化任务。
ansible-galaxy命令使用
# 查看已安装角色
[azurewhisky@controller web]$ ansible-galaxy list
# 搜索角色(需要网络连接)
[azurewhisky@controller ~]$ ansible-galaxy search --platforms=EL haproxy
# 查看角色详细信息
[azurewhisky@controller ~]$ ansible-galaxy info geerlingguy.docker
# 查看本地角色信息
[azurewhisky@controller web]$ ansible-galaxy info apache --offline
# 安装角色
[azurewhisky@controller ~]$ ansible-galaxy install geerlingguy.haproxy
批量安装角色
创建requirements.yml文件:
# requires.yml
- name: docker
src: https://github.com/geerlingguy/ansible-role-docker/archive/2.7.0.tar.gz
- name: haproxy
src: https://github.com/geerlingguy/ansible-role-haproxy/archive/1.1.2.tar.gz
批量安装:
[azurewhisky@controller ~]$ ansible-galaxy install -r requires.yml
其他管理命令
# 登录Galaxy
[azurewhisky@controller ~]$ ansible-galaxy login
# 删除角色
[azurewhisky@controller ~]$ ansible-galaxy remove role_name
# 登出
[azurewhisky@controller ~]$ ansible-galaxy logout
综合案例:部署Web集群
需求说明
- node3作为负载均衡器(HAProxy)
- node1和node2作为Web服务器
实施步骤
# 创建清单文件
[azurewhisky@controller web]$ cat > inventory <<EOF
[loadbalancers]
loadbalancer ansible_host=node3
[webservers]
node1
node2
EOF
# 安装所需角色
[azurewhisky@controller web]$ ansible-galaxy install geerlingguy.haproxy
[azurewhisky@controller web]$ ansible-galaxy install geerlingguy.apache
# 查看HAProxy角色文档了解配置参数
[azurewhisky@controller web]$ less roles/geerlingguy.haproxy/README.md
编写部署剧本
# deploy_web_cluster.yaml
---
- name: 部署负载均衡器
hosts: loadbalancers
vars:
haproxy_backend_servers: # 配置后端服务器
- name: node1
address: 10.1.8.11:80 # node1的IP和端口
- name: node2
address: 10.1.8.12:80 # node2的IP和端口
roles:
- geerlingguy.haproxy # 调用HAProxy角色
- name: 部署Web服务器
hosts: webservers
roles:
- geerlingguy.apache # 调用Apache角色
tasks:
- name: 创建首页内容
copy:
content: "Welcome to {{ ansible_fqdn }}.\n" # 动态生成内容
dest: /var/www/html/index.html
执行部署并验证
# 运行部署剧本
[azurewhisky@controller web]$ ansible-playbook deploy_web_cluster.yaml
# 测试负载均衡效果
[azurewhisky@controller web]$ curl http://node3/
Welcome to node1.azurewhisky.top.
[azurewhisky@controller web]$ curl http://node3/
Welcome to node2.azurewhisky.top.
通过这个完整的指南,您应该对Ansible角色管理有了深入的理解,能够创建、使用和管理角色,以及利用Ansible Galaxy中的社区资源来加速自动化部署。