目录结构就是约定
Ansible 大量行为依赖“文件放在哪”:清单与变量文件的相对位置决定变量是否生效,配置文件的查找顺序决定生效的并发度与连接参数,角色目录的位置决定能不能被找到。把这些约定固定成一套仓库结构,新人接手时不必猜,执行结果也不会因为换了目录而改变。
基本信息
| 清单位置 | inventory/ 目录,或单个清单文件;清单是目录时其中所有文件会被合并解析 |
|---|---|
| 变量位置 | 清单文件旁的 group_vars/ 与 host_vars/,以及 playbook 所在目录下的同名目录 |
| 清单级与剧本级 | 两处都存在时按变量优先级规则决定,实际取值需按官方文档确认 |
| 角色位置 | 项目 roles/ 目录,或在配置中指定角色搜索路径 |
| 集合依赖 | requirements 文件声明所需集合,用安装命令按版本拉取 |
| 关键前提 | ansible.cfg 的执行目录敏感,仓库内应自带一份并固定工作目录 |
典型使用场景
- 多环境仓库:inventory/ 下按环境各建一个清单目录,变量各归其位
- 团队统一:仓库自带清单路径与配置,任何人 clone 后命令一致
- 角色复用:通用角色集中在 roles/,项目 playbook 只做编排
- 依赖管理:把集合依赖写进 requirements 文件并锁定版本,避免版本漂移
- 权限隔离:生产清单与密钥单独存放并限制访问,测试环境保持宽松
- 可移植:路径尽量用相对路径,仓库整体搬迁后仍可直接执行
一套常见的仓库骨架
一套常见的仓库骨架
# 仓库根目录
# ansible.cfg 并发度、连接参数、清单默认路径
# site.yml 总入口,按角色或分组编排
# requirements.yml 所需集合与版本
# inventory/
# production/
# hosts.ini 生产清单
# group_vars/all/ 生产分组变量(明文与密文分开)
# staging/
# hosts.ini
# group_vars/all/
# playbooks/
# deploy.yml 具体编排
# maintenance.yml
# roles/
# nginx/ 通用角色,含 tasks、templates、defaults、handlers
# collections/
# ansible_collections/ 按需安装的集合,一般不入库
# filter_plugins/ library/ 自研过滤器与模块
#
# 执行:先切到仓库根目录,再运行,避免读到别处的配置
# cd /path/to/repo && ansible-playbook -i inventory/production site.yml文件归属
| 内容 | 放哪 | 原因 |
|---|---|---|
| 各环境共用的编排逻辑 | playbooks/ 与 roles/ | 复用,避免复制出多份逐渐分叉的剧本 |
| 环境专属参数 | inventory/<环境>/group_vars/ | 与环境绑定,切换清单即切换参数 |
| 主机的个别差异 | host_vars/ | 有针对性,不污染分组变量 |
| 秘密值 | 加密文件单列 | 加密范围最小,评审其余内容仍可读 |
| 自研扩展 | library/ 与 filter_plugins/ | 靠近项目,独立于版本发布节奏 |
| 第三方依赖 | requirements 文件声明 | 可复现地重建环境 |
清单是目录时,目录内所有文件都会被解析并合并成一份清单,这正好适合“基础分组 + 各环境补充”的拆分方式;但同名分组的变量仍遵守优先级规则,拆分时要明确谁负责定义什么,避免同一变量在两处各写一份。
仓库结构再整齐,也挡不住执行目录带来的差异:ansible.cfg 的查找包含当前工作目录,从别处执行会读到另一份配置,清单路径、并发度全部改变。自动化脚本里务必先固定工作目录,或用环境变量显式指定配置文件。
判断结构是否合理
看两个信号:一是换环境是否需要改动 playbook 内容(需要就说明环境参数没有沉淀进清单与变量),二是同一份文件里是否同时出现环境专属取值与通用逻辑(出现就说明分层没做干净)。这两点都过关时,新增一个环境基本只是复制变量文件并填值。