Ansible如何将预定义变量作为模块参数传入实现复用
Ansible原生支持将预定义的参数字典直接传入模块复用,完全可以满足分三类容器配置减少重复编写的需求,共有两种常用实现方案:
方案1:使用combine过滤器(推荐,适配所有场景)
这是通用性最强的方案,无论你的通用变量是定义在group_vars/host_vars、独立变量文件还是动态生成,都可以正常使用,不受YAML文件边界限制。
核心逻辑是通过Jinja2的combine过滤器,将通用参数字典和单个容器的专属参数字典合并为完整的模块参数字典,直接传给模块即可。
注意合并优先级:后传入combine的字典会覆盖前面字典的同名键值;如果存在嵌套字典需要深度合并,需要添加
recursive=True参数;列表类型参数(如networks/ports/volumes)的合并规则可通过list_merge参数配置,支持replace(默认,直接替换通用列表)、append(追加专属列表内容)、append_rp(去重追加)等模式,可根据实际需求选择。
对应traefik容器任务,写法如下:
- name: Launch traefik container docker_container: "{{ common_keys_core | combine({ 'name': 'traefik', 'image': 'traefik:latest', 'state': 'started', # 此处填写traefik专属参数,如端口、挂载、启动命令等 'ports': ['80:80', '443:443', '8080:8080'] }, recursive=True, list_merge='replace' ) }}"
如果某个容器需要覆盖通用配置的参数,比如core组默认restart: always,某容器需要改成restart: "no",直接在后面的专属字典里写对应key即可,合并时会自动覆盖通用值。
方案2:YAML原生锚点+<<合并(同文件场景可用)
如果你使用Ansible 2.10及以上版本,且通用配置和任务写在同一个YAML文件中,可以直接用Docker Compose同款<<合并语法,和YAML锚点配合使用,写法和Compose完全一致:
- hosts: your_docker_hosts vars: # 定义通用配置时直接打上YAML锚点 common_keys_core: &common_keys_core networks: - network1 restart: always common_keys_apps: &common_keys_apps networks: - network1 - proxy1 restart: unless-stopped common_keys_media: &common_keys_media networks: - network2 - proxy1 restart: "no" tasks: - name: Launch traefik container docker_container: name: traefik image: 'traefik:latest' state: started # 直接插入锚点引用的通用配置 <<: *common_keys_core # 后续写容器专属参数即可 ports: - "80:80" - "443:443"
这个方案的限制是YAML锚点无法跨文件引用,如果你把通用配置拆分到独立的变量文件中维护,锚点会失效,这种场景请使用方案1的combine过滤器。
选型建议
- 管理容器数量多、配置按场景拆分到不同变量文件维护的场景,优先选
combine过滤器,灵活度最高,没有兼容问题。 - 小规模Playbook、所有配置写在单文件内的场景,可以用锚点
<<写法,格式更直观,和Compose使用习惯一致。
内容的提问来源于stack exchange,提问作者Subbeh

