Ansible 复杂 Playbook 管理与角色化实践
一、Ansible 复杂 Play 与 Playbook 管理
在 Ansible 自动化运维中,面对多任务、多主机的复杂场景,需通过任务拆分、模块化导入、变量复用实现 Playbook 的轻量化与可维护性,核心围绕任务文件拆分、嵌套导入、通用任务封装展开实操。
1. 环境准备与基础 Playbook 编写
(1)切换工作目录
进入实验专属工作目录,统一管理 Playbook、任务文件及相关资源,执行命令:
cd ~/projects-review
(2)编写基础单文件 Playbook
编写playbook.yml实现 web 服务基础部署,包含 httpd 安装、启动、配置文件拷贝,指定单台 / 多台目标主机:
cat playbook.yml << 'EOF'
---
- name: Install and configure web service
hosts:
- servera.lab.example.com
- serverb.lab.example.com
- serverc.lab.example.com
- serverd.lab.example.com
tasks:
- name: Install httpd
ansible.builtin.dnf:
name: httpd
state: latest
- name: Enable and start httpd
ansible.builtin.service:
name: httpd
enabled: true
state: started
- name: Tuning configuration installed
ansible.builtin.copy:
src: files/tune.conf
dest: /etc/httpd/conf.d/tune.conf
owner: root
group: root
EOF
(3)内置变量测试主机匹配
编写host-test.yml,使用 Ansible 内置变量inventory_hostname测试通配符主机匹配规则,关闭事实收集提升执行效率:
cat > host-test.yml << 'EOF'
---
- name: List inventory hostnames
hosts: server*.lab.example.com
gather_facts: no
tasks:
- name: List inventory hostnames
ansible.builtin.debug:
msg: "{{ inventory_hostname }}"
EOF
执行测试命令,验证主机匹配结果:
ansible-navigator run -m stdout host-test.yml
(4)简化 Playbook 主机配置
修改playbook.yml,使用通配符简化多主机配置,适配批量部署场景:
vim playbook.yml
# 替换hosts配置为通配符形式
hosts: server*.lab.example.com
2. 任务文件拆分与静态导入
将基础 Playbook 中的任务按功能拆分,通过import_tasks实现任务文件的静态导入,实现任务模块化管理。
(1)创建任务目录
创建专属任务目录,统一存放拆分后的任务文件:
mkdir tasks
(2)拆分 web 服务核心任务
编写tasks/web_tasks.yml,封装 httpd 安装、启动、配置文件拷贝核心任务,配置 handler 触发条件:
cat > tasks/web_tasks.yml << "EOF"
---
- name: Install httpd
ansible.builtin.dnf:
name: httpd
state: latest
- name: Enable and start httpd
ansible.builtin.service:
name: httpd
enabled: true
state: started
- name: Tuning configuration installed
ansible.builtin.copy:
src: files/tune.conf
dest: /etc/httpd/conf.d/tune.conf
owner: root
group: root
mode: 0644
notify:
- restart httpd
EOF
(3)重构基础 Playbook 并导入任务
修改playbook.yml,通过import_tasks导入 web 核心任务,新增防火墙部署相关任务,定义 handler 实现配置变更后 httpd 重启:
cat > playbook.yml << "EOF"
---
- name: Install and configure web service
hosts: server*.lab.example.com
tasks:
- name: Import the web_tasks.yml task file
import_tasks: tasks/web_tasks.yml
- name: Install firewalld
ansible.builtin.dnf:
name: firewalld
state: latest
- name: Enable and start the firewall
ansible.builtin.service:
name: firewalld
enabled: true
state: started
- name: Open the port for http
ansible.posix.firewalld:
service: http
immediate: true
permanent: true
state: enabled
handlers:
- name: restart httpd
ansible.builtin.service:
name: httpd
state: restarted
EOF
3. 全量任务拆分与多层级导入
将防火墙任务也拆分独立文件,实现Playbook→核心任务文件→功能任务文件的多层级模块化管理,进一步提升可维护性。
(1)拆分防火墙任务文件
编写tasks/firewall_tasks.yml,封装防火墙安装、启动、http 端口开放任务:
cat > tasks/firewall_tasks.yml << "EOF"
---
- name: Install firewalld
ansible.builtin.dnf:
name: firewalld
state: latest
- name: Enable and start the firewall
ansible.builtin.service:
name: firewalld
enabled: true
state: started
- name: Open the port for http
ansible.posix.firewalld:
service: http
immediate: true
permanent: true
state: enabled
EOF
(2)重构 Playbook 实现多任务文件导入
修改playbook.yml,通过import_tasks分别导入 web 和防火墙任务文件,精简主 Playbook 内容:
cat > playbook.yml << "EOF"
---
- name: Install and configure web service
hosts: server*.lab.example.com
tasks:
- name: Import the web_tasks.yml task file
import_tasks: tasks/web_tasks.yml
- name: Import the firewall_tasks.yml task file
import_tasks: tasks/firewall_tasks.yml
handlers:
- name: restart httpd
ansible.builtin.service:
name: httpd
state: restarted
EOF
4. 通用任务封装与变量传参
提取软件安装 + 服务启动的通用逻辑,封装为可复用任务文件,通过变量传参实现多服务适配,实现任务逻辑的最大化复用。
(1)封装通用任务文件
编写tasks/install_and_enable.yml,定义package和service通用变量,适配任意软件的安装与服务启动:
cat > tasks/install_and_enable.yml << "EOF"
---
- name: Install {{ package }}
ansible.builtin.dnf:
name: "{{ package }}"
state: latest
- name: Enable and start {{ service }}
ansible.builtin.service:
name: "{{ service }}"
enabled: true
state: started
EOF
(2)修改子任务文件实现变量传参
修改tasks/web_tasks.yml,导入通用任务文件并传递 httpd 相关变量:
cat > tasks/web_tasks.yml << "EOF"
---
- name: Install and start httpd
import_tasks: install_and_enable.yml
vars:
package: httpd
service: httpd
- name: Tuning configuration installed
ansible.builtin.copy:
src: files/tune.conf
dest: /etc/httpd/conf.d/tune.conf
owner: root
group: root
mode: 0644
notify:
- restart httpd
EOF
修改tasks/firewall_tasks.yml,导入通用任务文件并传递 firewalld 相关变量:
cat > tasks/firewall_tasks.yml << "EOF"
---
- name: Install and start firewalld
import_tasks: install_and_enable.yml
vars:
package: firewalld
service: firewalld
- name: Open the port for http
ansible.posix.firewalld:
service: http
immediate: true
permanent: true
state: enabled
EOF
5. Playbook 语法检查与执行
完成多层级任务封装与导入后,先进行语法校验,再执行 Playbook 实现批量部署。
(1)语法检查
执行语法检查命令,验证 Playbook 及所有导入任务文件的语法合法性:
ansible-navigator run -m stdout playbook.yml --syntax-check
(2)执行 Playbook
执行最终的 Playbook,实现目标主机的 web 服务与防火墙自动化部署:
ansible-navigator run -m stdout playbook.yml
二、使用角色和 Ansible 内容集合简化 Playbook
Ansible角色(Role) 和内容集合(Collection) 是实现自动化代码标准化、可复用的核心特性,通过角色封装完整的功能逻辑,通过集合管理角色与相关资源,大幅简化复杂场景的 Playbook 编写。
1. 环境准备与内容集合安装
(1)切换工作目录
进入角色实验专属工作目录:
cd ~/role-review
(2)安装 Ansible 内容集合
将redhat.rhel_system_roles集合安装到项目本地collections/目录,实现本地资源隔离:
ansible-galaxy collection install -p collections/ redhat-rhel_system_roles-1.19.3.tar.gz
(3)验证集合安装结果
执行命令查看已安装的集合,确认版本与路径正确性:
ansible-galaxy collection list
2. 基础角色化 Playbook 编写
编写基础 Playbookweb_dev_server.yml,指定目标主机组,开启强制处理程序确保 handler 必执行:
vim web_dev_server.yml << 'EOF'
---
- name: Configure Dev Web Server
hosts: dev_webserver
force_handlers: yes
EOF
(1)语法检查与基础执行
# 语法检查
ansible-navigator run -m stdout web_dev_server.yml --syntax-check
# 基础执行
ansible-navigator run -m stdout web_dev_server.yml
3. 从 Git 仓库拉取现成角色
通过requirements.yml配置 Git 仓库中的现成角色,实现角色的自动化拉取与安装,提升开发效率。
(1)创建角色目录
mkdir -v roles
(2)编写角色拉取配置文件
编写roles/requirements.yml,指定 Git 仓库地址、版本控制系统、角色版本:
vim roles/requirements.yml << 'EOF'
- name: infra.apache
src: git@workstation.lab.example.com:infra/apache
scm: git
version: v1.4
EOF
(3)拉取并安装角色
执行命令从 Git 仓库拉取指定版本的角色,安装到项目本地roles/目录:
ansible-galaxy install -r roles/requirements.yml -p roles
4. 自定义角色创建与依赖配置
通过ansible-galaxy init创建标准化自定义角色,配置角色依赖实现功能复用,封装专属业务逻辑。
(1)创建自定义角色目录结构
使用ansible-galaxy init自动生成标准化的自定义角色apache.developer_configs目录结构:
cd roles
ansible-galaxy init apache.developer_configs
cd ..
(2)配置角色依赖
修改自定义角色的元数据文件roles/apache.developer_configs/meta/main.yml,指定依赖的现成角色infra.apache:
vim roles/apache.developer_configs/meta/main.yml << 'EOF'
dependencies:
- name: infra.apache
src: git@workstation.lab.example.com:infra/apache
scm: git
version: v1.4
EOF
(3)填充自定义角色资源
将业务相关的任务文件和模板文件放入自定义角色的指定目录,实现资源封装:
# 覆盖角色任务文件
mv -v developer_tasks.yml roles/apache.developer_configs/tasks/main.yml
# 移动Jinja2模板文件到角色模板目录
mv -v developer.conf.j2 roles/apache.developer_configs/templates/
5. 组变量配置与角色引用
通过组变量(group_vars) 为目标主机组统一配置变量,在 Playbook 中引用自定义角色,实现角色的自动化执行。
(1)创建组变量目录并配置变量
# 创建目标主机组的组变量目录
mkdir -pv group_vars/dev_webserver
# 移动变量文件到组变量目录
mv -v web_developers.yml group_vars/dev_webserver/
(2)在 Playbook 中引用自定义角色
修改web_dev_server.yml,添加roles节点引用自定义角色apache.developer_configs:
vim web_dev_server.yml << 'EOF'
---
- name: Configure Dev Web Server
hosts: dev_webserver
force_handlers: yes
roles:
- apache.developer_configs
EOF
(3)语法检查与执行
# 语法检查
ansible-navigator run -m stdout web_dev_server.yml --syntax-check
# 执行Playbook
ansible-navigator run -m stdout web_dev_server.yml
6. 前置任务配置与 Block-Rescue 异常处理
通过pre_tasks 配置系统级前置检查任务,结合Block-Rescue异常处理结构,实现 SELinux 配置的容错性处理,确保核心部署任务的稳定性。
(1)配置 pre_tasks 前置任务
修改web_dev_server.yml,添加pre_tasks节点,封装 SELinux 配置的异常处理逻辑:
vim web_dev_server.yml << 'EOF'
---
- name: Configure Dev Web Server
hosts: dev_webserver
force_handlers: yes
pre_tasks:
- name: Verify SELinux configuration
block:
- include_role:
name: redhat.rhel_system_roles.selinux
rescue:
- name: Handle general failure
ansible.builtin.fail:
msg: "SELinux role failed."
when: not selinux_reboot_required
- name: Restart managed host
ansible.builtin.reboot:
msg: "Ansible rebooting system for updates."
- name: Reapply SELinux role to complete changes
include_role:
name: redhat.rhel_system_roles.selinux
roles:
- apache.developer_configs
EOF
(2)配置 SELinux 组变量
将 SELinux 相关变量文件移动到目标主机组的组变量目录,实现 SELinux 配置的统一管理:
mv -v selinux.yml group_vars/dev_webserver/
(3)语法检查与最终执行
# 语法检查
ansible-navigator run -m stdout web_dev_server.yml --syntax-check
# 最终执行
ansible-navigator run -m stdout web_dev_server.yml
7. 部署结果验证
通过curl命令访问目标主机的 web 服务,验证角色化部署的最终效果:
curl servera
curl servera:9081
curl servera:9082
三、核心知识点总结
- 复杂 Playbook 管理 :通过
import_tasks实现任务文件的静态拆分与多层级导入,提取通用逻辑封装为可复用任务文件,通过变量传参适配多服务场景,大幅提升 Playbook 可维护性; - Ansible 内容集合 :通过
ansible-galaxy collection实现集合的本地安装与管理,实现自动化资源的隔离与复用,是企业级 Ansible 开发的标准规范; - 角色(Role) :通过
ansible-galaxy init生成标准化角色目录,支持现成角色拉取 和自定义角色开发 ,配置meta/main.yml实现角色依赖管理,封装完整的业务功能逻辑; - 变量与前置任务 :通过组变量(group_vars) 为目标主机组统一配置变量,通过
pre_tasks实现系统级前置检查,结合force_handlers确保 handler 强制执行; - 异常处理 :在
pre_tasks中结合Block-Rescue结构实现异常捕获与容错处理,支持服务重启、角色重执行等逻辑,提升 Playbook 的健壮性。