首页/系统与基础设施/自动化运维速查/变量合并与覆盖行为的判读
Ansible 核心70 条

变量合并与覆盖行为的判读

Ansible 对同名变量默认整块替换而非逐键合并,字典要保留下层键需用合并过滤器(嵌套加递归参数),列表追加要用并集运算;合并意图必须显式写出,不能依赖已废弃的全局开关。

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

默认是替换不是合并

同名变量出现在多层时,Ansible 默认用高优先级的整个值替换低优先级的值,而不是逐键合并。后果最明显的是字典:高优先级层只写了其中几个键,低优先级层里其余的键会一起消失。想要真正的合并,必须用合并过滤器显式表达。判断口诀很简单——默认永远替换,合并要自己写出来。

基本信息

默认行为同名变量整体替换,高优先级覆盖低优先级
字典合并combine 过滤器,嵌套字典可加递归参数
列表处理合并过滤器不处理列表元素,需要并集运算
排查手段打印整个字典看最终结构,而不是只看单个键

典型使用场景

  • 基线配置在分组变量里定义,环境差异只覆盖少数字段:用合并过滤器保住其余键
  • 需要追加而不是替换列表项:用并集运算或列表相加
  • 多层嵌套配置(数据库、缓存、超时)合并:指定递归合并,避免内层整块被替换
  • 排查某个键丢失:把结果字典整体打印出来对照各层定义
  • 角色默认值与环境覆盖配合:默认值里放全量键,减少缺键概率

覆盖与合并的差别

覆盖与合并的差别
- name: 默认行为是整块替换  # 本层没有的键会一起消失
  ansible.builtin.debug:
    msg: "{{ env_over }}"
  vars:
    base: {timeout: 30, retries: 3}
    env_over: {timeout: 60}

- name: 显式合并保留下层键  # 嵌套字典再加递归参数
  ansible.builtin.debug:
    msg: "{{ base | combine(env_over) }}"

- name: 列表要并集而不是覆盖  # 合并过滤器不管列表元素
  ansible.builtin.debug:
    msg: "{{ old_list | union(new_list) }}"
  vars:
    old_list: [80, 443]
    new_list: [8080]

场景与写法

场景默认行为怎么表达想要的效果
字典同名整体替换用合并过滤器,嵌套时加递归参数
列表同名整体替换用并集运算或列表相加
标量同名高优先级生效无需额外操作,确认来源即可
缺键的字典低优先级键消失先补全键再合并,或逐层合并
递归参数决定嵌套字典是逐层合并还是整块替换。配置嵌套越深越要显式写明,否则外层合并成功、内层却丢了半截配置,表面上看不出来。
依赖全局合并开关改变默认行为的写法已被废弃:升级后语义会变,别人接手时也看不出合并发生在哪里。把合并写进表达式才是可迁移的做法。

怎么设计变量层次

减少合并需求的做法是让每一层只负责自己的键:分组变量放全量基线,主机变量只放这台机器的差异,环境差异集中在环境目录。键的归属清晰之后,绝大多数情况用不到合并;真正需要合并时,也容易判断哪些键是从下层继承来的。

易错点

  • 以为同名字典会自动合并,只覆盖了一个键却把其余键一起弄丢
  • 对列表使用合并过滤器,列表仍是替换而非追加,得到缺项的结果
  • 嵌套字典没加递归参数,内层整块被替换,看着合并成功实际丢配置
  • 靠全局合并开关改变行为,跨版本升级后语义与之前不同
  • 出问题只打印单个键,看不到整体结构,无法判断是覆盖还是未定义

数据来源与参考

  • Ansible 官方文档 Filter reference(combine/union)
  • Ansible 官方文档 Variable precedence
  • Ansible 配置参考中关于全局合并开关的历史说明

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

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