第六章:Roles 角色¶
什么是 Roles?¶
Roles 是 Ansible 组织 Playbook 的标准化方式,将变量、任务、模板、文件等按目录结构组织,实现代码复用和模块化。
Roles 目录结构¶
roles/
└── nginx/
├── tasks/
│ └── main.yml # 主任务文件
├── handlers/
│ └── main.yml # 处理器
├── templates/
│ └── nginx.conf.j2 # Jinja2 模板
├── files/
│ └── index.html # 静态文件
├── vars/
│ └── main.yml # 角色变量(高优先级)
├── defaults/
│ └── main.yml # 默认变量(低优先级)
├── meta/
│ └── main.yml # 角色依赖
├── library/ # 自定义模块
├── module_utils/ # 模块工具
└── README.md # 角色文档
创建 Role¶
使用 ansible-galaxy 创建¶
手动创建¶
Role 组成部分¶
tasks/main.yml¶
# roles/nginx/tasks/main.yml
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
tags: install
- name: Create web directory
ansible.builtin.file:
path: "{{ nginx_root }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
tags: config
- name: Deploy nginx config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: Reload nginx
tags: config
- name: Deploy site config
ansible.builtin.template:
src: site.conf.j2
dest: "/etc/nginx/sites-available/{{ server_name }}"
mode: '0644'
notify: Reload nginx
tags: config
- name: Enable site
ansible.builtin.file:
src: "/etc/nginx/sites-available/{{ server_name }}"
dest: "/etc/nginx/sites-enabled/{{ server_name }}"
state: link
notify: Reload nginx
tags: config
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
enabled: yes
tags: service
handlers/main.yml¶
# roles/nginx/handlers/main.yml
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
defaults/main.yml¶
# roles/nginx/defaults/main.yml
# 默认变量(可被覆盖)
nginx_root: /var/www/html
nginx_user: www-data
nginx_worker_processes: auto
nginx_worker_connections: 1024
http_port: 80
server_name: localhost
vars/main.yml¶
# roles/nginx/vars/main.yml
# 角色变量(高优先级,通常不覆盖)
nginx_config_path: /etc/nginx
nginx_log_path: /var/log/nginx
templates/nginx.conf.j2¶
# roles/nginx/templates/nginx.conf.j2
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
error_log {{ nginx_log_path }}/error.log;
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log {{ nginx_log_path }}/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/sites-enabled/*;
}
templates/site.conf.j2¶
# roles/nginx/templates/site.conf.j2
server {
listen {{ http_port }};
server_name {{ server_name }};
root {{ nginx_root }};
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
meta/main.yml¶
# roles/nginx/meta/main.yml
galaxy_info:
author: Your Name
description: Nginx web server role
company: Your Company
license: MIT
min_ansible_version: '2.9'
platforms:
- name: Ubuntu
versions:
- focal
- jammy
galaxy_tags:
- nginx
- web
- server
dependencies:
- role: common
vars:
some_var: value
使用 Role¶
在 Playbook 中使用¶
# site.yml
- name: Deploy web servers
hosts: webservers
become: yes
roles:
- nginx
- role: mysql
vars:
mysql_root_password: secret
- role: php
tags: php
带条件的 Role¶
- name: Deploy web servers
hosts: all
become: yes
roles:
- role: nginx
when: "'webservers' in group_names"
- role: mysql
when: "'dbservers' in group_names"
Role 依赖¶
# roles/nginx/meta/main.yml
dependencies:
- role: common
- role: selinux
when: ansible_selinux.status == "enabled"
Ansible Galaxy¶
搜索 Role¶
安装 Role¶
# 安装角色
ansible-galaxy install geerlingguy.nginx
# 安装指定版本
ansible-galaxy install geerlingguy.nginx,v1.0.0
# 安装到指定目录
ansible-galaxy install geerlingguy.nginx -p ./roles
# 从 Git 安装
ansible-galaxy install git+https://github.com/geerlingguy/ansible-role-nginx.git
requirements.yml¶
# requirements.yml
- src: geerlingguy.nginx
version: v3.1.0
- src: geerlingguy.mysql
version: v4.3.0
- src: https://github.com/user/ansible-role-custom.git
name: custom-role
- src: git@github.com:user/private-role.git
scm: git
version: main
# 安装所有依赖
ansible-galaxy install -r requirements.yml
# 强制重新安装
ansible-galaxy install -r requirements.yml --force
发布 Role¶
# 登录 Ansible Galaxy
ansible-galaxy login
# 导入角色
ansible-galaxy import github_user role_name
# 发布到 Galaxy
# 1. 在 GitHub 创建仓库
# 2. 添加 meta/main.yml
# 3. 在 Galaxy 网站导入
实战示例:完整 LAMP Stack¶
目录结构¶
lamp/
├── site.yml
├── inventory.ini
├── roles/
│ ├── common/
│ │ └── tasks/
│ │ └── main.yml
│ ├── nginx/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── templates/
│ │ │ ├── nginx.conf.j2
│ │ │ └── site.conf.j2
│ │ └── defaults/
│ │ └── main.yml
│ ├── mysql/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── templates/
│ │ │ └── my.cnf.j2
│ │ └── defaults/
│ │ └── main.yml
│ └── php/
│ ├── tasks/
│ │ └── main.yml
│ └── defaults/
│ └── main.yml
└── group_vars/
└── all.yml
site.yml¶
roles/common/tasks/main.yml¶
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Install common packages
ansible.builtin.apt:
name:
- vim
- git
- curl
- wget
- unzip
state: present
- name: Set timezone
community.general.timezone:
name: "{{ timezone }}"
roles/mysql/tasks/main.yml¶
- name: Install MySQL
ansible.builtin.apt:
name:
- mysql-server
- mysql-client
- python3-mysqldb
state: present
- name: Start MySQL
ansible.builtin.service:
name: mysql
state: started
enabled: yes
- name: Set root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
login_unix_socket: /var/run/mysqld/mysqld.sock
- name: Create database
mysql_db:
name: "{{ mysql_database }}"
state: present
login_user: root
login_password: "{{ mysql_root_password }}"
- name: Create user
mysql_user:
name: "{{ mysql_user }}"
password: "{{ mysql_password }}"
priv: "{{ mysql_database }}.*:ALL"
state: present
login_user: root
login_password: "{{ mysql_root_password }}"
roles/php/tasks/main.yml¶
- name: Add PHP repository
ansible.builtin.apt_repository:
repo: ppa:ondrej/php
state: present
- name: Install PHP
ansible.builtin.apt:
name:
- php{{ php_version }}
- php{{ php_version }}-fpm
- php{{ php_version }}-mysql
- php{{ php_version }}-curl
- php{{ php_version }}-gd
- php{{ php_version }}-mbstring
- php{{ php_version }}-xml
state: present
- name: Start PHP-FPM
ansible.builtin.service:
name: "php{{ php_version }}-fpm"
state: started
enabled: yes
group_vars/all.yml¶
timezone: Asia/Shanghai
# Nginx
nginx_root: /var/www/html
http_port: 80
server_name: localhost
# MySQL
mysql_root_password: "{{ vault_mysql_root_password }}"
mysql_database: myapp
mysql_user: myapp
mysql_password: "{{ vault_mysql_password }}"
# PHP
php_version: "8.1"
最佳实践¶
1. 角色命名¶
2. 使用 defaults¶
# defaults/main.yml
# 提供合理的默认值
nginx_port: 80
nginx_root: /var/www/html
# 允许用户覆盖
# 在 playbook 或 inventory 中设置
3. 使用 Tags¶
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
tags:
- install
- nginx
4. 文档化¶
# roles/nginx/README.md
# Nginx Role
## Description
Installs and configures Nginx web server.
## Requirements
- Ubuntu 20.04/22.04
## Variables
| Variable | Default | Description |
|----------|---------|-------------|
| nginx_port | 80 | HTTP port |
| nginx_root | /var/www/html | Web root |
## Dependencies
- common
## Example Playbook
```yaml
- hosts: webservers
roles:
- nginx
小结¶
本章学习了:
- ✅ Roles 概念和目录结构
- ✅ 创建和使用 Roles
- ✅ Ansible Galaxy 使用
- ✅ 实战示例:LAMP Stack
- ✅ 最佳实践
总结¶
通过这六章的学习,你已经掌握了:
- Ansible 基础 - 概念、架构、安装
- Inventory - 主机清单配置
- Ad-hoc 命令 - 临时命令执行
- Playbook - 自动化剧本编写
- Roles - 代码组织和复用
继续学习:Kubernetes 教程 - 容器编排和集群管理。