Orange的运维学习日记--48.Ansible进阶之Import与Role
Ansible角色与RHEL系统角色管理摘要 Ansible角色采用标准化目录结构(由ansible-galaxy init生成),包含tasks、handlers、templates等组件,实现模块化复用。角色支持变量覆盖、依赖声明和多种调用方式,执行顺序为pre_tasks→roles→tasks→post_tasks。RHEL系统角色(rhel-system-roles包)提供跨版本统一配置
Orange的运维学习日记–48.Ansible进阶之Import与Role
文章目录
实验环境
mkdir web && cd web
cat > ansible.cfg <<'EOF'
[defaults]
remote_user = example
inventory = ./inventory
[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF
cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF
Ansible 角色管理
角色介绍
Ansible 角色提供一种标准化目录结构,将任务、变量、文件、模板、处理程序及依赖打包为可复用组件
角色结构
执行 ansible-galaxy init <role_name> 可生成以下目录结构
<role_name>/
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
├── tests/
│ ├── inventory
│ └── test.yml
└── vars/
└── main.yml
- defaults:提供默认变量,可在清单变量或 play vars 中被覆盖
- files:存放静态文件
- handlers:定义处理程序(handlers)
- meta:角色元信息(作者、许可证、平台、依赖等)
- tasks:角色主要执行任务
- templates:存放 Jinja2 模板
- vars:定义角色内部变量,优先级高于清单和 play vars
- tests:用于验证角色的测试清单和 playbook
- README.md:记录角色用途、用法示例及非 Ansible 要求

角色目录位置
默认搜索路径(优先级从高到低)
- ~/.ansible/roles
- /usr/share/ansible/roles
- /etc/ansible/roles
可在 ansible.cfg [defaults] 块中通过 roles_path 变量自定义
[defaults]
roles_path = ./roles:/etc/ansible/roles
创建角色
mkdir roles
ansible-galaxy init apache --init-path=./roles
- apache was created successfully
示例:Apache 角色
-
defaults/main.yml
--- web_package: httpd web_service: httpd -
tasks/main.yml
--- - name: install web yum: name: "{{ web_package }}" state: latest - name: "start {{ web_service }}" service: name: "{{ web_service }}" state: started enabled: yes - name: prepare motd template: src: motd.j2 dest: /etc/motd - name: prepare site config template: src: example.conf.j2 dest: /etc/httpd/conf.d/example.conf notify: - restart_web - name: create DocumentRoot file: path: "/var/www/html/{{ ansible_hostname }}" state: directory - name: prepare index.html template: src: index.html.j2 dest: "/var/www/html/{{ ansible_hostname }}/index.html" -
handlers/main.yml
--- - name: restart_web service: name: "{{ web_service }}" state: restarted -
templates/motd.j2
hello guys! Welcome to {{ ansible_fqdn }}! -
templates/example.conf.j2
## {{ ansible_managed }} <VirtualHost *:80> ServerAdmin example@{{ 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> -
templates/index.html.j2
Welcome to {{ ansible_fqdn }} ! -
meta/main.yml
--- galaxy_info: author: example description: example web company: example world license: GPLv2 min_ansible_version: 2.4 platforms: - name: Fedora versions: [all, 25] - name: SomePlatform versions: [all] galaxy_tags: [apache, web] dependencies: []
调用角色
-
语法一
--- - hosts: servers roles: - apache -
语法二(传递变量)
--- - hosts: servers roles: - role: apache var1: value1 - { role: other_role, var2: value2 }
角色依赖
在 meta/main.yml 中定义依赖关系,被依赖角色将自动执行
dependencies:
- role: firewall
service: http
任务执行顺序
- pre_tasks
- roles 中的 tasks
- playbook 中的 tasks
- post_tasks
Handlers 执行顺序
- pre_tasks 触发的 handlers
- roles 中 tasks 触发的 handlers
- playbook tasks 触发的 handlers
- post_tasks 触发的 handlers
include_role 与 import_role
import_role:静态导入,执行前解析角色并展开include_role:动态包含,运行时加载角色,可配合 when 条件
角色优势
- 模块化复用,降低重复代码
- 并行开发,提高协作效率
- 易于管理大型项目
推荐做法
- 不在角色中存储敏感信息,使用 Ansible Vault 或环境变量注入
- 使用
ansible-galaxy init并删除不需要的目录 - 维护 README.md 和 meta/main.yml 文档
- 拆分职责单一的角色,避免过度臃肿
- 重用并重构已有角色,避免重复创建边缘角色
- 将角色纳入版本控制
RHEL 系统角色概述
系统角色由 rhel-system-roles 软件包提供,自 RHEL 7.4 起可用,用于标准化 RHEL 6.10+ 和 RHEL 7/8 主机的配置
通过 Ansible 角色方式统一管理跨不同发行版的配置项,简化管理员维护多套配置文件的工作
安装与文档位置
-
安装系统角色
sudo yum install -y rhel-system-roles -
默认角色路径
/usr/share/ansible/roles/ -
文档存放目录
/usr/share/doc/rhel-system-roles/每个角色目录下包含 README.md,说明角色用途、变量及示例用法
timesync 角色
用于统一配置 RHEL 6/7/8 的时间同步服务,无需手动维护 chronyd/ntpd 配置
关键变量
-
timesync_ntp_servers:列表格式,定义要同步的 NTP 服务器
hostname:服务器主机名或地址minpoll:最小轮询间隔,默认 6maxpoll:最大轮询间隔,默认 10iburst:启动时快速同步,布尔值,默认 nopool:将解析到的每个地址视为单独服务器,默认 no
示例 Playbook
- hosts: targets
vars:
timesync_ntp_servers:
- hostname: foo..com
iburst: yes
- hostname: bar..com
iburst: yes
- hostname: baz..com
iburst: yes
roles:
- rhel-system-roles.timesync
设置时区示例
- name: Time Synchronization
hosts: node1
vars:
timesync_ntp_servers:
- hostname: classroom..com
iburst: yes
timezone: "Asia/Shanghai"
roles:
- rhel-system-roles.timesync
tasks:
- name: Set timezone
timezone:
name: "{{ timezone }}"
selinux 角色
简化 SELinux 管理,通过变量驱动配置,无需编写重复任务
功能
- 设置 SELinux 模式(enforcing 或 permissive)
- 恢复文件上下文(restorecon)
- 配置 SELinux 布尔值
- 永久设置文件上下文(fcontexts)
- 管理 SELinux 用户映射
- 配置 SELinux 端口
示例 1:基础配置
- hosts: node1
vars:
selinux_state: permissive
selinux_booleans:
- name: httpd_enable_homedirs
state: on
persistent: yes
selinux_fcontexts:
- target: '/srv/www(/.*)?'
setype: httpd_sys_content_t
state: present
selinux_restore_dirs:
- /srv/www
selinux_ports:
- ports: 82
setype: http_port_t
proto: tcp
state: present
roles:
- rhel-system-roles.selinux
示例 2:切换模式并重启
- hosts: node1,node2
vars:
selinux_state: enforcing
selinux_booleans:
- name: samba_enable_home_dirs
state: on
tasks:
- block:
- name: Apply SELinux role
include_role:
name: rhel-system-roles.selinux
rescue:
- name: Check for non-reboot failures
fail:
when: not selinux_reboot_required
- name: Restart managed host
reboot:
- name: Reapply SELinux role
include_role:
name: rhel-system-roles.selinux
使用 Ansible Galaxy 管理角色
Ansible Galaxy 是社区仓库,提供大量角色和集合,方便自动化任务实现和复用
ansible-galaxy 常用命令
ansible-galaxy // 管理角色与集合的入口命令
ansible-galaxy role -h // 查看角色子命令
ansible-galaxy collection // 管理 Galaxy 集合
子命令示例:
- init 初始化角色目录结构
- install 安装角色(URL、tarball 或 Galaxy 名称)
- remove 删除本地角色
- delete 从 Galaxy 删除角色(不影响 GitHub 仓库)
- list 列出本地已安装角色
- search 按平台、标签、作者搜索角色
- info 显示角色详细信息
本地角色操作
-
列表
ansible-galaxy list -
查看详细信息(离线)
ansible-galaxy info apache --offline
在线搜索与安装
-
搜索示例
ansible-galaxy search --platforms=EL docker ansible-galaxy search --author geerlingguy haproxy -
安装单个角色
ansible-galaxy install geerlingguy.haproxy -
批量安装(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.gzansible-galaxy install -r requires.yml
角色管理其他命令
- 登录 Galaxy:
ansible-galaxy login - 注销 Galaxy:
ansible-galaxy logout - 删除本地角色:
ansible-galaxy remove <role_name>或直接rm -rf roles/<role_name> - 从 Galaxy 删除角色:
ansible-galaxy delete <role_name>
综合案例:部署 Web 集群
环境需求
- node3 作为 HAProxy 负载均衡
- node1/node2 作为 Apache Web 服务器
步骤概要
-
编辑 inventory
[loadbalancers] loadbalancer ansible_host=node3 [webservers] node1 node2 -
安装角色
ansible-galaxy install geerlingguy.haproxy ansible-galaxy install geerlingguy.apache -
查看角色变量说明
vim roles/geerlingguy.haproxy/README.md -
编写 Playbook
deploy_web_cluster.yaml--- - name: deploy LB hosts: loadbalancers vars: haproxy_backend_servers: - name: node1 address: 10.1.8.11:80 - name: node2 address: 10.1.8.12:80 roles: - geerlingguy.haproxy - name: deploy web servers hosts: webservers roles: - geerlingguy.apache tasks: - name: prepare index.html copy: content: "Welcome to {{ ansible_fqdn }}\n" dest: /var/www/html/index.html -
执行 Playbook
ansible-playbook deploy_web_cluster.yaml -
验证结果
curl http://node3/ ## 轮询返回 node1 和 node2 欢迎页面
包含(include)与导入(import)
Ansible 支持通过 include/import 将 Playbook 或任务拆分成更小组件,提升复用性和可维护性
模块化方式
- 动态包含:
include_tasks、include_role等,在运行时加载内容 - 静态导入:
import_playbook、import_tasks、import_role等,在解析阶段展开内容 - 旧版
include关键字将在 Ansible 2.12 中移除,建议使用新版 include/import
Playbook 级别:import_playbook
- 用于导入完整 Playbook
- 在主 Playbook 中按顺序执行多个子 Playbook
示例主 Playbook:
- name: prepare the web server
import_playbook: pre_web.yml
- name: prepare the vsftpd server
import_playbook: pre_vsftpd.yml
- name: prepare the database server
import_playbook: pre_db.yml
Task 级别:import_tasks 与 include_tasks
import_tasks:静态导入子任务,解析时展开include_tasks:动态包含子任务,运行时加载
示例主 Playbook:
---
- name: Install web server
hosts: node1
tasks:
- name: load task file
import_tasks: tasks.yaml
## 或者
## include_tasks: tasks.yaml
示例 tasks.yaml:
- name: Install httpd
yum:
name: httpd
state: present
- name: Start httpd
service:
name: httpd
state: started
include_vars 模块
用于在任务中动态加载外部变量文件
---
- name: Install web application packages
hosts: node1
tasks:
- name: include variables
include_vars: variables.yml
- name: show loaded variables
debug:
msg: "{{ packages.web_package }} and {{ packages.db_package }} are loaded"
## variables.yml
---
packages:
web_package: httpd
db_package: mariadb-server
动态包含 与 静态导入 差异
- 选项应用时机不同:静态导入会复制父选项到子任务,动态包含仅在运行时生效
--list-tasks/--list-tags:动态包含内部的标签和任务不会显示- 句柄触发:动态包含无法通过 notify 触发内部 handler,只能触发包含本身;静态导入可直接触发内部 handler
- 语法检查:静态导入在预解析阶段检测错误;动态包含仅在执行时检测
- 循环支持:include 与 loop 联合可对每个元素多次加载子任务;import 不支持循环加载
- 变量生命周期:静态导入前解析,动态包含在运行时解析
场景示例
列出任务与标签
- 使用
include_tasks时,子任务的标签不在--list-tags输出中 - 使用
import_tasks时,子任务标签会出现在列表中
Handler 触发
- name: install httpd
yum:
name: httpd
notify: restart_httpd
handlers:
- name: restart_httpd
include_tasks: tasks.yaml
## 或 import_tasks: tasks.yaml
- include_tasks 时,notify 只能触发包含整体
- import_tasks 时,可触发子任务里的指定 handler
Syntax Check
ansible-playbook --syntax-check会在解析阶段检测 import_tasks 中的语法错误- include_tasks 中的错误只有执行到包含时才会报
Loop 加载
- name: install services
include_tasks: tasks.yaml
loop:
- httpd
- vsftpd
tasks.yaml:
- name: install {{ item }}
yum:
name: "{{ item }}"
state: present
- name: start {{ item }}
service:
name: "{{ item }}"
state: restarted
条件包含与变量作用域
- name: debug before
debug: msg="{{ ansible_os_family }}"
- include_tasks: tasks.yaml
when: ansible_os_family == "RedHat"
- name: debug after
debug: msg="{{ ansible_os_family }}"
包含整体
- import_tasks 时,可触发子任务里的指定 handler
Syntax Check
ansible-playbook --syntax-check会在解析阶段检测 import_tasks 中的语法错误- include_tasks 中的错误只有执行到包含时才会报
Loop 加载
- name: install services
include_tasks: tasks.yaml
loop:
- httpd
- vsftpd
tasks.yaml:
- name: install {{ item }}
yum:
name: "{{ item }}"
state: present
- name: start {{ item }}
service:
name: "{{ item }}"
state: restarted
条件包含与变量作用域
- name: debug before
debug: msg="{{ ansible_os_family }}"
- include_tasks: tasks.yaml
when: ansible_os_family == "RedHat"
- name: debug after
debug: msg="{{ ansible_os_family }}"
tasks.yaml 中可 set_fact 覆盖变量,在动态包含后可见;静态导入无法跨任务修改父级变量
更多推荐




所有评论(0)