Role 目录结构与 Ansible Galaxy
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read415 words

Role 目录结构与 Ansible Galaxy

核心问题:Playbook 越写越长、各项目重复逻辑越来越多——怎样把 Playbook 组织成可复用的"角色库"?


为什么要用 Role

当你的 Playbook 超过 100 行,或者多个项目需要复用相同配置逻辑时,把代码拆成 Role 是必要的:

问题 Role 如何解决
Playbook 文件太长,难以维护 按功能拆分,每个 Role 管一件事
多个项目重复同样的 Nginx 配置 提取为 nginx Role,各项目 import
不同环境的变量覆盖难以管理 Role 有 defaults/(可覆盖)和 vars/(强制)两级变量
团队协作时任务职责不清晰 按 Role 分工:infra team 写 base Role,dev team 写 app Role

Role 标准目录结构

roles/
└── nginx/                       # Role 名称
├── tasks/
│   ├── main.yml             # 任务入口(必须有)
│   ├── install.yml          # 安装任务(由 main.yml include)
│   └── configure.yml        # 配置任务
├── handlers/
│   └── main.yml             # Handler 定义
├── templates/
│   ├── nginx.conf.j2        # Jinja2 模板
│   └── vhost.conf.j2
├── files/
│   └── mime.types           # 静态文件(直接 copy)
├── vars/
│   └── main.yml             # 强制变量(优先级高,不易被覆盖)
├── defaults/
│   └── main.yml             # 默认变量(优先级最低,设计为可覆盖)
├── meta/
│   └── main.yml             # Role 元数据、依赖声明
└── README.md

各目录详解

defaults/main.yml — 默认变量

# roles/nginx/defaults/main.yml
# 这里的值是"建议默认值",调用者可以随意覆盖
nginx_port: 80
nginx_user: www-data
nginx_worker_processes: auto
nginx_worker_connections: 1024
ssl_enabled: false
nginx_access_log: /var/log/nginx/access.log

vars/main.yml — 强制变量

# roles/nginx/vars/main.yml
# 这里的值不应该被调用者轻易覆盖(只有 -e 命令行参数能覆盖)
nginx_config_dir: /etc/nginx
nginx_sites_available: /etc/nginx/sites-available
nginx_sites_enabled: /etc/nginx/sites-enabled

tasks/main.yml — 任务入口

# roles/nginx/tasks/main.yml
---
- name: 安装 Nginx
import_tasks: install.yml
tags: [nginx, install]
- name: 配置 Nginx
import_tasks: configure.yml
tags: [nginx, config]

tasks/install.yml

---
- name: 安装 Nginx 软件包
apt:
name: nginx
state: present
update_cache: true
- name: 确保 Nginx 开机自启
systemd:
name: nginx
enabled: true
state: started

tasks/configure.yml

---
- name: 生成 Nginx 主配置
template:
src: nginx.conf.j2
dest: "{{ nginx_config_dir }}/nginx.conf"
owner: root
mode: "0644"
validate: "nginx -t -c %s"   # 应用前自动验证语法
notify: 重载 Nginx
- name: 删除默认虚拟主机
file:
path: "{{ nginx_sites_enabled }}/default"
state: absent
notify: 重载 Nginx
- name: 配置虚拟主机
template:
src: vhost.conf.j2
dest: "{{ nginx_sites_available }}/{{ item.domain }}"
loop: "{{ vhosts | default([]) }}"
notify: 重载 Nginx
- name: 启用虚拟主机
file:
src: "{{ nginx_sites_available }}/{{ item.domain }}"
dest: "{{ nginx_sites_enabled }}/{{ item.domain }}"
state: link
loop: "{{ vhosts | default([]) }}"
notify: 重载 Nginx

handlers/main.yml

---
- name: 重载 Nginx
service:
name: nginx
state: reloaded
- name: 重启 Nginx
service:
name: nginx
state: restarted

meta/main.yml — 依赖声明

# roles/nginx/meta/main.yml
galaxy_info:
role_name: nginx
author: myorg
description: "安装并配置 Nginx Web 服务器"
min_ansible_version: "2.14"
platforms:
- name: Ubuntu
versions: ["22.04", "24.04"]
dependencies:
- role: base           # 先运行 base Role(安装基础工具)
- role: firewall       # 先运行 firewall Role(开放端口)
vars:
open_ports: [80, 443]

使用 Role

# site.yml
---
- name: 配置 Web 服务器
hosts: webservers
become: true
roles:
- role: base           # 最简形式
- role: nginx          # 使用默认变量
- role: app
vars:                # 覆盖 Role 默认变量
app_port: 3000
app_env: production

Ansible Galaxy:公共 Role 仓库

Ansible Galaxy 是官方 Role/Collection 仓库,包含数万个社区 Role。

查找和安装 Role

# 搜索
ansible-galaxy role search nginx
# 查看 Role 详情
ansible-galaxy role info geerlingguy.nginx
# 安装(到默认 ~/.ansible/roles/)
ansible-galaxy role install geerlingguy.nginx
# 安装到项目 roles/ 目录
ansible-galaxy role install geerlingguy.nginx -p roles/
# 安装特定版本
ansible-galaxy role install geerlingguy.nginx,3.2.0

requirements.yml — 依赖清单

团队协作时,统一用 requirements.yml 管理依赖,不把第三方 Role 提交到 Git:

# requirements.yml
---
roles:
- name: geerlingguy.nginx
version: "3.2.0"
- name: geerlingguy.certbot
version: "5.1.0"
- src: https://github.com/myorg/private-role.git
scm: git
version: main
name: myorg.private_role
collections:
- name: amazon.aws
version: "6.5.0"
- name: community.postgresql
version: "3.2.0"
# 安装所有依赖
ansible-galaxy install -r requirements.yml -p roles/
# CI 中执行(忽略已安装版本检查)
ansible-galaxy install -r requirements.yml -p roles/ --force

项目最佳目录结构

myproject/
├── ansible.cfg
├── site.yml                  # 主入口:import 各 playbook
├── webservers.yml            # Web 服务器 Playbook
├── databases.yml             # 数据库 Playbook
├── requirements.yml          # Galaxy 依赖
├── inventory/
│   ├── production/
│   │   ├── hosts.yml
│   │   ├── group_vars/
│   │   └── host_vars/
│   └── staging/
│       ├── hosts.yml
│       └── group_vars/
├── roles/
│   ├── base/                 # 自写:基础工具
│   ├── nginx/                # 自写:Nginx 配置
│   └── app/                  # 自写:应用部署
└── playbooks/
├── deploy.yml
└── rollback.yml

常见错误

错误 原因 解决
role 'nginx' was not found Role 路径不对 检查 roles_pathansible.cfg)或用绝对路径
循环依赖:role A 依赖 B,B 依赖 A meta 依赖设计问题 提取公共部分为独立 common Role
defaults/ 变量被 Inventory 变量覆盖 这是设计行为(defaults 优先级最低) 如果不想被覆盖,放到 vars/main.yml
Galaxy Role 与本地 Role 重名 命名冲突 Galaxy Role 用 namespace.role 格式(如 geerlingguy.nginx

下一节Jinja2 模板实战