如何深度合并Helm命名模板中的数组?
Helm模板合并:实现数组对象的深度合并
当前尝试的模板与合并逻辑
我尝试合并两个Helm命名模板,简化示例如下:
{{- define "common.t1" -}} a1: "t1-a1" a2: "t1-a2" b1: c1: t1-b1-c1 c2: t1-b1-c2 d1: - name: container1 e1: t1-d1-e1 e2: t1-d1-e2 - name: container2 {{- end -}} {{- define "this.t2" -}} a1: "t2-a1" a3: "t2-a3" b1: c1: t2-b1-c1 c3: t2-b1-c3 d1: - name: container1 e1: t2-d1-e1 e3: t2-d1-e3 - name: container3 {{- end -}} {{- $t1 := fromYaml (include "common.t1" .) -}} {{- $t2 := fromYaml (include "this.t2" .) -}} {{ toYaml (merge $t2 $t1) }}
当前merge函数的输出结果
使用merge函数合并后,d1数组中的对象被完全覆盖,结果如下:
a1: t2-a1 a2: t1-a2 a3: t2-a3 b1: c1: t2-b1-c1 c2: t1-b1-c2 c3: t2-b1-c3 d1: - e1: t2-d1-e1 e3: t2-d1-e3 name: container1 - name: container3
预期的合并结果
我需要针对数组中的对象按name字段做合并:同名对象合并属性,保留未被覆盖的原有项,新增对象直接添加,预期结果如下:
a1: t2-a1 a2: t1-a2 a3: t2-a3 b1: c1: t2-b1-c1 c2: t1-b1-c2 c3: t2-b1-c3 d1: - e1: t2-d1-e1 e2: t1-d1-e2 e3: t2-d1-e3 name: container1 - name: container2 - name: container3
实际应用场景
这个合并需求是为了将通用Kubernetes Deployment模板放在公共库Chart中,让业务Chart基于通用模板做扩展,以此简化数十个Helm Chart的开发与维护。实际场景示例如下:
{{ magicMerge "common.deployment" "mychart548.deployment" . }} {{- define "mychart548.deployment" -}} spec: template: spec: containers: - name: {{ include "common.names.name" . }} envFrom: - configMapRef: name: {{ include "common.names.envConfigmapName" . }} env: - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: {{ include "common.names.fullname" . }}-postgress key: postgres-password {{- end -}}
解决方案:自定义深度合并函数
Helm内置的merge/mergeOverwrite函数无法处理数组对象的合并,需要自定义模板函数实现按指定键(如name)合并数组的逻辑。
实现步骤
- 在公共Chart的
_helpers.tpl中添加自定义合并函数:
{{- define "common.mergeArraysByName" -}} {{- $arr1 := index . 0 -}} {{- $arr2 := index . 1 -}} {{- $merged := dict -}} {{- /* 将第一个数组的对象存入字典,以name为键 */ -}} {{- range $item := $arr1 -}} {{- $_ := set $merged $item.name $item -}} {{- end -}} {{- /* 遍历第二个数组,合并到字典中 */ -}} {{- range $item := $arr2 -}} {{- if hasKey $merged $item.name -}} {{- $_ := set $merged $item.name (merge $item (index $merged $item.name)) -}} {{- else -}} {{- $_ := set $merged $item.name $item -}} {{- end -}} {{- end -}} {{- /* 将字典转回数组 */ -}} {{- $result := list -}} {{- range $key, $val := $merged -}} {{- $_ := append $result $val -}} {{- end -}} {{- toYaml $result -}} {{- end -}}
- 修改主合并逻辑,针对数组字段单独处理:
{{- $t1 := fromYaml (include "common.t1" .) -}} {{- $t2 := fromYaml (include "this.t2" .) -}} {{- /* 先合并非数组字段 */ -}} {{- $base := merge $t2 $t1 -}} {{- /* 处理d1数组的合并 */ -}} {{- $mergedD1 := fromYaml (include "common.mergeArraysByName" (list $t1.d1 $t2.d1)) -}} {{- $_ := set $base "d1" $mergedD1 -}} {{- toYaml $base -}}
说明
- 该函数通过将数组转为字典实现对象匹配,递归合并同名对象的属性,最后转回数组。
- 可根据需求扩展函数,支持自定义匹配键或处理多层嵌套数组的场景。
内容的提问来源于stack exchange,提问作者Stan B
相关产品推荐
相关产品推荐

