角色目录是一套固定约定
角色的可复用性来自目录约定:把任务、模板、文件、处理器、默认参数各放各的位置,调用者只需传变量就能用。约定固定之后,Ansible 会自动按目录名去找资源——模板里写文件名就能找到,不需要写路径。理解每个目录的语义,是角色能被多人维护的前提。
基本信息
| 入口 | 任务目录下的主文件是角色的执行起点 |
|---|---|
| 对外参数 | 默认值目录里定义的变量可被调用方覆盖,是角色的对外接口 |
| 内部取值 | 角色自身变量目录里的取值优先级更高,适合放不希望被随意覆盖的常量 |
| 资源目录 | 模板、普通文件、处理器目录分别存放渲染模板、原样分发的文件与变化后触发的动作 |
| 元数据 | 元信息文件声明依赖与角色描述 |
| 初始化 | 用官方提供的角色初始化命令生成标准目录,再按需删减 |
典型使用场景
- 中间件标准化:把安装、配置、启动、加固固化为一个角色供多项目引用
- 基线统一:用户、时区、日志、安全参数集中在一个基线角色里
- 多人协作:模板、任务、默认值各归其位,改动互不干扰
- 参数化交付:调用方只改默认值目录里声明的变量,不碰角色内部实现
- 测试与演练:资源目录结构固定后,可单独对角色做验证
- 版本演进:角色可独立打标签与版本号,逐步升级
目录语义
目录语义
# roles/myapp/
# tasks/main.yml 执行起点,可拆成多个任务文件按需引入
# handlers/main.yml 变化后触发的动作,例如重载服务
# templates/*.j2 需要按变量渲染的配置模板
# files/ 原样分发的文件(证书、安装包、许可证)
# defaults/main.yml 对外参数:调用方可覆盖,优先级最低
# vars/main.yml 角色内部取值:优先级高,不要放环境差异
# meta/main.yml 依赖声明与角色描述
# library/ filter_plugins/ 角色自带的自研模块与过滤器
# tests/ 最小可运行的验证剧本
#
# 生成标准结构(再删除用不到的目录)
# ansible-galaxy role init roles/myapp
#
# 常用引入方式(yaml 片段)
# - name: 应用配置
# ansible.builtin.import_tasks: config.yml # 静态引入,条件会作用于其中每个任务
# - name: 运行步骤
# ansible.builtin.include_tasks: "{{ step }}.yml" # 动态引入,可循环、可用运行时变量目录职责速查
| 目录 | 放什么 | 常见误用 |
|---|---|---|
| 任务 | 步骤,按阶段拆分 | 把变量取值直接写死在里面 |
| 默认值 | 对外可覆盖的参数 | 把秘密或环境专属值放这里 |
| 角色变量 | 内部常量 | 把需要调用方调整的参数放这里,导致无法覆盖 |
| 模板 | 需要渲染的配置内容 | 把不需要变量的文件也放进来 |
| 文件 | 原样分发的资源 | 放超大文件,拖慢分发 |
| 处理器 | 变化后的动作 | 在处理器里做需要条件的复杂操作 |
| 元数据 | 依赖与描述 | 依赖成环或声明了不存在的角色 |
模板与文件目录的约定带来一个便利:任务里只写文件名,Ansible 会自动到角色目录下查找,不需要拼路径。也因此同一个角色内不要出现同名模板与文件,否则引用时容易拿错。
秘密值不要放进角色目录:角色会被多个项目复用甚至公开分发,凭据应放在调用方的清单变量层并由加密文件保护。角色自身只声明“需要一个什么变量”,不持有具体值。
怎么判断角色拆分是否合理
看两个信号:调用方是否需要了解角色内部实现才能正确使用(需要就说明接口没收敛);角色内部是否出现特定环境或特定主机的取值(出现就说明职责越界)。合格的角色对外的全部信息就是默认值目录里那些变量,加上元数据里声明的依赖。