Ansible Roles #
什么是 Roles? #
Roles 是 Ansible 组织自动化内容的标准方式,将任务、变量、文件、模板等按功能模块化,实现代码复用和共享。
text
┌─────────────────────────────────────────────────────────────┐
│ Roles 结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ roles/ │
│ └── nginx/ │
│ ├── tasks/ # 任务 │
│ ├── handlers/ # 处理器 │
│ ├── templates/ # 模板 │
│ ├── files/ # 静态文件 │
│ ├── vars/ # 变量(高优先级) │
│ ├── defaults/ # 默认变量(低优先级) │
│ ├── meta/ # 元数据/依赖 │
│ └── README.md # 文档 │
│ │
└─────────────────────────────────────────────────────────────┘
角色目录结构 #
标准结构 #
text
roles/
└── nginx/
├── defaults/
│ └── main.yml # 默认变量(最低优先级)
├── files/
│ ├── index.html # 静态文件
│ └── favicon.ico
├── handlers/
│ └── main.yml # 处理器
├── meta/
│ └── main.yml # 角色依赖和元数据
├── tasks/
│ ├── main.yml # 主任务文件
│ ├── install.yml # 安装任务
│ ├── configure.yml # 配置任务
│ └── service.yml # 服务任务
├── templates/
│ ├── nginx.conf.j2 # 配置模板
│ └── site.conf.j2 # 站点模板
├── vars/
│ └── main.yml # 角色变量(高优先级)
├── library/
│ └── custom_module.py # 自定义模块
├── module_utils/
│ └── helper.py # 模块工具
├── tests/
│ ├── inventory # 测试清单
│ └── test.yml # 测试 Playbook
└── README.md # 角色文档
目录说明 #
| 目录 | 说明 | 文件名 |
|---|---|---|
| defaults | 默认变量,最低优先级 | main.yml |
| vars | 角色变量,高优先级 | main.yml |
| tasks | 任务定义 | main.yml |
| handlers | 处理器定义 | main.yml |
| templates | Jinja2 模板文件 | *.j2 |
| files | 静态文件 | * |
| meta | 角色依赖和元数据 | main.yml |
| library | 自定义模块 | *.py |
| module_utils | 模块工具 | *.py |
| tests | 测试文件 | test.yml |
创建角色 #
使用 ansible-galaxy #
bash
# 创建角色骨架
ansible-galaxy init nginx
# 创建角色到指定目录
ansible-galaxy init --init-path ./roles nginx
# 输出
- nginx was created successfully
手动创建 #
bash
# 创建目录结构
mkdir -p roles/nginx/{tasks,handlers,templates,files,vars,defaults,meta}
# 创建必要文件
touch roles/nginx/tasks/main.yml
touch roles/nginx/handlers/main.yml
touch roles/nginx/defaults/main.yml
touch roles/nginx/meta/main.yml
角色示例 #
defaults/main.yml #
yaml
# roles/nginx/defaults/main.yml
---
nginx_user: www-data
nginx_group: www-data
nginx_port: 80
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_log_dir: /var/log/nginx
nginx_config_dir: /etc/nginx
nginx_document_root: /var/www/html
nginx_vhosts: []
nginx_upstreams: []
nginx_gzip_enabled: true
nginx_ssl_enabled: false
vars/main.yml #
yaml
# roles/nginx/vars/main.yml
---
nginx_packages:
- nginx
- nginx-common
nginx_service_name: nginx
nginx_config_files:
- nginx.conf
- mime.types
nginx_log_files:
- access.log
- error.log
tasks/main.yml #
yaml
# roles/nginx/tasks/main.yml
---
- name: Include install tasks
include_tasks: install.yml
tags: install
- name: Include configure tasks
include_tasks: configure.yml
tags: configure
- name: Include vhost tasks
include_tasks: vhosts.yml
when: nginx_vhosts | length > 0
tags: vhosts
- name: Include service tasks
include_tasks: service.yml
tags: service
tasks/install.yml #
yaml
# roles/nginx/tasks/install.yml
---
- name: Install Nginx
apt:
name: "{{ nginx_packages }}"
state: present
update_cache: yes
when: ansible_facts['os_family'] == 'Debian'
- name: Install Nginx (RedHat)
yum:
name: nginx
state: present
when: ansible_facts['os_family'] == 'RedHat'
- name: Create nginx user
user:
name: "{{ nginx_user }}"
system: yes
shell: /sbin/nologin
create_home: no
when: nginx_user != 'www-data'
- name: Create directories
file:
path: "{{ item }}"
state: directory
owner: "{{ nginx_user }}"
group: "{{ nginx_group }}"
mode: '0755'
loop:
- "{{ nginx_log_dir }}"
- "{{ nginx_document_root }}"
tasks/configure.yml #
yaml
# roles/nginx/tasks/configure.yml
---
- name: Deploy nginx configuration
template:
src: nginx.conf.j2
dest: "{{ nginx_config_dir }}/nginx.conf"
owner: root
group: root
mode: '0644'
backup: yes
validate: nginx -t -c %s
notify: Reload Nginx
- name: Deploy mime types
copy:
src: mime.types
dest: "{{ nginx_config_dir }}/mime.types"
owner: root
group: root
mode: '0644'
notify: Reload Nginx
- name: Remove default site
file:
path: "{{ nginx_config_dir }}/sites-enabled/default"
state: absent
when: nginx_remove_default_site | default(true)
notify: Reload Nginx
tasks/vhosts.yml #
yaml
# roles/nginx/tasks/vhosts.yml
---
- name: Create vhost directories
file:
path: "{{ nginx_config_dir }}/sites-{{ item }}"
state: directory
owner: root
group: root
mode: '0755'
loop:
- available
- enabled
- name: Deploy vhost configurations
template:
src: vhost.conf.j2
dest: "{{ nginx_config_dir }}/sites-available/{{ item.server_name }}.conf"
owner: root
group: root
mode: '0644'
loop: "{{ nginx_vhosts }}"
notify: Reload Nginx
- name: Enable vhosts
file:
src: "{{ nginx_config_dir }}/sites-available/{{ item.server_name }}.conf"
dest: "{{ nginx_config_dir }}/sites-enabled/{{ item.server_name }}.conf"
state: link
loop: "{{ nginx_vhosts }}"
when: item.enabled | default(true)
notify: Reload Nginx
tasks/service.yml #
yaml
# roles/nginx/tasks/service.yml
---
- name: Ensure Nginx is started and enabled
service:
name: "{{ nginx_service_name }}"
state: started
enabled: yes
handlers/main.yml #
yaml
# roles/nginx/handlers/main.yml
---
- name: Reload Nginx
service:
name: nginx
state: reloaded
- name: Restart Nginx
service:
name: nginx
state: restarted
- name: Validate Nginx config
command: nginx -t
changed_when: false
templates/nginx.conf.j2 #
jinja2
{# roles/nginx/templates/nginx.conf.j2 #}
# Nginx configuration
# Managed by Ansible
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
pid /run/nginx.pid;
error_log {{ nginx_log_dir }}/error.log;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
{% if nginx_gzip_enabled %}
gzip on;
gzip_types text/plain text/css application/json application/javascript;
{% endif %}
{% for upstream in nginx_upstreams %}
upstream {{ upstream.name }} {
{% for server in upstream.servers %}
server {{ server }};
{% endfor %}
}
{% endfor %}
include {{ nginx_config_dir }}/conf.d/*.conf;
include {{ nginx_config_dir }}/sites-enabled/*;
}
meta/main.yml #
yaml
# roles/nginx/meta/main.yml
---
galaxy_info:
author: Your Name
description: Nginx web server installation and configuration
company: Your Company
license: MIT
min_ansible_version: '2.9'
platforms:
- name: Ubuntu
versions:
- focal
- jammy
- name: Debian
versions:
- bullseye
- bookworm
- name: EL
versions:
- '7'
- '8'
- '9'
galaxy_tags:
- web
- nginx
- server
dependencies: []
使用角色 #
基本使用 #
yaml
# site.yml
---
- hosts: webservers
become: yes
roles:
- nginx
传递变量 #
yaml
# site.yml
---
- hosts: webservers
become: yes
roles:
- role: nginx
vars:
nginx_port: 8080
nginx_worker_processes: 4
nginx_vhosts:
- server_name: example.com
port: 80
root: /var/www/example
条件执行 #
yaml
# site.yml
---
- hosts: all
become: yes
roles:
- role: nginx
when: "'webserver' in group_names"
- role: mysql
when: "'database' in group_names"
使用标签 #
yaml
# site.yml
---
- hosts: webservers
become: yes
roles:
- role: nginx
tags:
- web
- nginx
include_role #
yaml
# site.yml
---
- hosts: webservers
become: yes
tasks:
- name: Include nginx role
include_role:
name: nginx
vars:
nginx_port: 8080
when: install_nginx | default(true)
import_role #
yaml
# site.yml
---
- hosts: webservers
become: yes
tasks:
- name: Import nginx role
import_role:
name: nginx
角色依赖 #
定义依赖 #
yaml
# roles/webapp/meta/main.yml
---
dependencies:
- role: nginx
nginx_port: 80
nginx_vhosts:
- server_name: "{{ app_domain }}"
root: "{{ app_root }}"
- role: php
php_version: "8.1"
- role: mysql
when: app_needs_database | default(true)
依赖顺序 #
text
执行顺序:
1. 依赖角色(按定义顺序)
├── nginx
├── php
└── mysql
2. 当前角色
└── webapp
3. 处理器(按触发顺序)
避免循环依赖 #
yaml
# 错误示例 - 循环依赖
# roles/nginx/meta/main.yml
dependencies:
- role: ssl
# roles/ssl/meta/main.yml
dependencies:
- role: nginx
# 这会导致循环依赖错误
Ansible Galaxy #
什么是 Ansible Galaxy? #
Ansible Galaxy 是 Ansible 角色的社区仓库,可以分享和下载角色。
安装角色 #
bash
# 从 Galaxy 安装
ansible-galaxy install geerlingguy.nginx
# 安装指定版本
ansible-galaxy install geerlingguy.nginx,v3.1.0
# 从 Git 安装
ansible-galaxy install git+https://github.com/geerlingguy/ansible-role-nginx.git
# 从文件安装多个角色
ansible-galaxy install -r requirements.yml
requirements.yml #
yaml
# requirements.yml
- src: geerlingguy.nginx
version: "3.1.0"
- src: geerlingguy.mysql
version: "4.0.0"
- src: https://github.com/user/ansible-role-custom
name: custom-role
- src: git+https://github.com/user/ansible-role-app.git
version: main
name: app
发布角色 #
bash
# 登录 Galaxy
ansible-galaxy login
# 导入角色
ansible-galaxy import username role_name
# 从 GitHub 自动导入
# 在 Galaxy 网站上连接 GitHub 账户
角色最佳实践 #
1. 使用 defaults 定义可覆盖变量 #
yaml
# roles/nginx/defaults/main.yml
nginx_port: 80 # 用户可覆盖
nginx_user: www-data # 用户可覆盖
nginx_config_dir: /etc/nginx # 通常不需要覆盖
2. 使用 vars 定义内部变量 #
yaml
# roles/nginx/vars/main.yml
nginx_packages: # 内部使用,不建议覆盖
- nginx
- nginx-common
3. 模块化任务文件 #
yaml
# roles/nginx/tasks/main.yml
---
- include_tasks: install.yml
- include_tasks: configure.yml
- include_tasks: vhosts.yml
- include_tasks: service.yml
4. 使用标签 #
yaml
# roles/nginx/tasks/main.yml
---
- include_tasks: install.yml
tags: install
- include_tasks: configure.yml
tags: configure
- include_tasks: service.yml
tags: service
5. 提供完整的 README #
markdown
# roles/nginx/README.md
# Ansible Role: Nginx
Installs and configures Nginx web server.
## Requirements
- Ubuntu 20.04/22.04 or Debian 10/11
- Ansible 2.9+
## Role Variables
| Variable | Default | Description |
|----------|---------|-------------|
| nginx_port | 80 | Nginx listen port |
| nginx_user | www-data | Nginx user |
| nginx_worker_processes | auto | Number of worker processes |
## Dependencies
None
## Example Playbook
```yaml
- hosts: webservers
roles:
- role: nginx
nginx_port: 8080
License #
MIT
text
### 6. 编写测试
```yaml
# roles/nginx/tests/test.yml
---
- hosts: localhost
remote_user: root
roles:
- nginx
vars:
nginx_port: 8080
nginx_vhosts:
- server_name: test.local
root: /var/www/test
完整项目示例 #
text
project/
├── ansible.cfg
├── inventory/
│ ├── hosts
│ ├── group_vars/
│ │ ├── all.yml
│ │ └── webservers.yml
│ └── host_vars/
│ └── web1.yml
├── roles/
│ ├── common/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ └── defaults/
│ │ └── main.yml
│ ├── nginx/
│ │ ├── tasks/
│ │ ├── handlers/
│ │ ├── templates/
│ │ ├── defaults/
│ │ └── meta/
│ └── webapp/
│ ├── tasks/
│ ├── templates/
│ ├── defaults/
│ └── meta/
├── playbooks/
│ ├── site.yml
│ ├── webservers.yml
│ └── databases.yml
└── requirements.yml
yaml
# playbooks/site.yml
---
- hosts: all
become: yes
roles:
- common
- hosts: webservers
become: yes
roles:
- nginx
- webapp
- hosts: databases
become: yes
roles:
- mysql
下一步 #
现在你已经掌握了 Roles 角色,接下来学习 常用模块 了解 Ansible 内置模块的详细用法!
最后更新:2026-03-29