变量为什么会有分歧
Ansible 的变量不是一张全局表,而是由二十多个来源按固定优先级逐层合并出来的结果:同一个名字可能同时存在于角色默认值、清单分组变量、主机变量、play 变量和命令行覆盖里,最终只有一个值生效。梳理变量的方法就两步:先确定它定义在哪一层,再对照优先级判断谁压过谁。绝大多数“值不对”的困惑,本质是把某一层的作用域想大了。
基本信息
| 优先级方向 | extra vars 最高,role defaults 最低 |
|---|---|
| 常见来源 | role defaults、group_vars、host_vars、play vars、role vars、task vars、-e |
| 合并粒度 | 按主机分别计算,不同主机可得到不同结果 |
| 查看工具 | ansible-inventory --list、debug 模块打印单机取值 |
典型使用场景
- 同一变量在不同环境取不同值:用分环境的分组变量目录分层表达
- 临时验证某个取值:命令行传 extra vars,一次运行内生效且优先级最高
- 角色对外暴露可调参数:写在角色的 defaults 里,调用方按需覆盖
- 角色内部不希望被外层改动:写进角色 vars,明确表示这是实现细节
- 排查取值不符合预期:用 debug 打印实际值,再回到优先级表定位来源
查看与覆盖
查看与覆盖
# 优先级由低到高:role defaults -> inventory group_vars -> host_vars
# -> play vars -> role vars -> block/task vars -> extra vars(完整顺序以官方文档为准)
ansible-inventory -i inventories/prod --list # 看清单算出的分组与主机变量
ansible -i inventories/prod web -m debug -a 'var=nginx_port' # 单机查实际取值
ansible-playbook -i inventories/prod site.yml -e nginx_port=8080 # 临时覆盖,优先级最高层级与用途
| 来源 | 生效范围 | 典型用途 |
|---|---|---|
| role defaults | 该角色被调用的所有位置,可被外层覆盖 | 给角色留默认参数 |
| group_vars/all | 清单内全部主机 | 全局基线配置 |
| host_vars | 单台主机 | 机器特有参数 |
| play vars | 当前 play | 编排层参数 |
| extra vars | 本次运行的全部任务 | 临时覆盖与调试 |
同名变量在两个不同层级都定义时,不要靠记忆判断结果,直接查优先级表;想要显式合并两个字典(而不是后者覆盖前者),用 combine 过滤器在表达式里写清楚。
用命令行覆盖生产参数只是临时手段:一旦写进自动化脚本或计划任务,重跑时行为会与前一次不一致,长期覆盖应固化到对应层级的变量文件。
梳理顺序建议
遇到变量问题,按“由外到内”查一遍:先看命令行有没有传值,再看 play 与角色调用处有没有直接赋值,接着看主机与分组变量目录,最后才是角色的默认值。反过来按“由内到外”查容易漏掉外层,误以为角色写错了。查完把结论记进变更记录,下次同样的问题不必再猜一遍。