首页/系统与基础设施/自动化运维速查/角色变量的默认值与覆盖方式
Ansible 核心70 条

角色变量的默认值与覆盖方式

角色默认值目录是对外接口、优先级最低,适合放可调参数与兜底值;角色变量目录优先级高于清单变量,适合放内部常量。环境差异应在清单侧覆盖,调用方在角色引用处传参优先级更高,命令行额外变量最高但只应临时使用。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌‌​​‌‌​​​​‌​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​​​​‌​‌‌​​​‌​​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​​‌‌​​‌‌​​​​‌​‌‌‌​‌​‌​‌‌​‌‌​​​‌‌‌​‌​​​‌‌‌​​‌‌​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​‌‌​​‌‌​​‌​‌​‌‌‌​​‌​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

两套变量目录决定谁能被覆盖

角色里有两处放变量的地方,优先级完全不同:默认值目录的变量优先级最低,几乎任何外部定义都能覆盖它;角色变量目录的优先级高于清单里的分组变量。于是它们承担不同职责:默认值目录是角色的对外接口,列出所有可调参数;角色变量目录放内部常量,调用方不需要也不应该去改。

基本信息

默认值目录对外参数,可被清单变量、剧本变量、传参覆盖
角色变量目录内部常量,优先级高于清单分组变量,外部不易覆盖
传参方式在角色引用处直接给变量,优先级高于以上两者
命名建议对外参数统一加角色名前缀,避免与其它角色或清单变量撞名
秘密处理默认值里不写真实秘密,只声明需要调用方提供
验证方法打印最终取值,或对照变量优先级文档确认覆盖链

典型使用场景

  • 对外提供可调参数:端口、路径、工作进程数放进默认值目录
  • 内部固定取值:包名、服务单元名、内部目录布局放进角色变量目录
  • 多环境取值不同:环境差异通过清单变量覆盖默认值,角色本身不变
  • 单点覆盖:某个主机需要不同参数时用主机变量覆盖,不影响其它主机
  • 临时试验:用额外变量在命令行临时覆盖取值,验证后再落到清单
  • 接口收敛:默认值目录成为角色文档,调用方一眼看到可调项

两套目录的分工

两套目录的分工
# roles/app/defaults/main.yml  对外接口,可被外部覆盖
# app_port: 8080
# app_worker_processes: 2
# app_log_level: info
# app_conf_dir: /etc/app

# roles/app/vars/main.yml    内部常量,不该被环境差异影响
# app_service_name: app
# app_pkg_name: app-server
# app_state_dir: /var/lib/app

# 调用方覆盖的三种方式
- hosts: web
  roles:
    - role: app
      vars:
        app_worker_processes: 8        # 角色传参,优先级最高
  tasks:
    - name: 临时查看最终取值
      ansible.builtin.debug:
        var: app_worker_processes

# 清单侧覆盖(优先级低于角色变量目录,高于默认值)
# group_vars/web/vars.yml
#   app_log_level: debug

覆盖优先级直觉版

定义位置相对高低用途
角色默认值目录最低对外接口与兜底值
清单分组变量与主机变量较高环境与主机差异
角色变量目录高角色内部常量
角色引用处传参更高调用方明确指定
命令行额外变量最高临时覆盖,排障与试验
覆盖不生效时,先怀疑三件事:参数写在了角色变量目录(优先级过高)、参数名拼写或前缀不一致、覆盖写在了优先级更低的位置。用调试任务打印最终取值,比反复改文件快得多。
把需要按环境调整的取值写进角色变量目录,会让外部覆盖失效,调用方只能去改角色代码,复用性随之丧失。凡是“别人可能想调”的参数,一律放默认值目录。

接口设计的判断

一个成熟角色的默认值目录应当像一份参数说明:变量名带前缀、有合理兜底、注释写清用途与取值范围。凡是调用方需要知道内部实现才能传对的参数,说明接口还没设计好——要么补默认值,要么把它变成内部常量。

易错点

  • 把需要按环境调整的参数写进角色变量目录,外部覆盖无效,只能改角色代码
  • 对外参数不加前缀,与清单或其它角色的变量撞名,取值来源难以判断
  • 在默认值目录里写真实口令或内网地址,角色被复用时把秘密带出去
  • 覆盖写在优先级更低的位置,改了不生效且不容易发现原因
  • 用命令行额外变量长期覆盖,配置散落在执行命令里,无法沉淀进仓库

数据来源与参考

  • Ansible 官方文档 Roles 变量与 defaults/vars 的区别
  • Ansible 官方文档 Variable precedence: where should I put a variable
  • Ansible 官方文档 Roles 传参方式

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/role-variable-defaults-override.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​‌‌‌‌​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌‌​‌‌​​‌‌​​​​‌​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​​​​‌​‌‌​​​‌​​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌​​‌‌​​‌‌​​​​‌​‌‌‌​‌​‌​‌‌​‌‌​​​‌‌‌​‌​​​‌‌‌​​‌‌​​‌​‌‌​‌​‌‌​‌‌‌‌​‌‌‌​‌‌​​‌‌​​‌​‌​‌‌‌​​‌​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​​‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​