Helm 3中合并字典问题:如何合并数组内的端口配置字典
解决Helm中合并数组内字典的问题
问题原因
Helm的merge和mergeDeep函数在处理数组时,会直接替换整个数组,而不会合并数组内部的字典元素。你当前的ports是数组类型,无论调换merge的参数顺序,都会导致其中一个数组完全覆盖另一个,无法将两个数组里的字典字段合并。
解决方案
方案1:使用mergeDeepWith自定义数组合并逻辑
通过mergeDeepWith传入自定义合并函数,针对数组场景做特殊处理(比如合并单元素数组内的字典):
{{- /* 自定义合并函数:处理单元素数组的字典合并,非数组场景使用默认merge逻辑 */}} {{- define "common.mergeArrays" }} {{- $source := index . 0 }} {{- $dest := index . 1 }} {{- if and (kindIs "slice" $source) (kindIs "slice" $dest) }} {{- /* 针对单元素数组,合并两个数组内的字典 */}} {{- if and (eq (len $source) 1) (eq (len $dest) 1) }} {{- list (merge (first $dest) (first $source)) }} {{- else }} {{- /* 多元素数组场景:可扩展按name字段匹配合并,这里默认保留目标数组 */}} {{- $dest }} {{- end }} {{- else }} {{- merge $dest $source }} {{- end }} {{- end }} {{- /* 应用自定义合并逻辑 */}} {{- $deployment := mergeDeepWith (include "common.mergeArrays" .) .Values.common.deployment .Values.deployment }}
执行后$deployment的ports会合并所有字段,得到你期望的结果:
deployment: ports: - name: http protocol: TCP containerPort: 8081
方案2:手动合并单元素数组(简单场景)
如果确认ports始终是单元素数组,可以直接提取两个数组的字典并合并:
{{- /* 提取两个ports字典 */}} {{- $commonPort := default dict (first .Values.common.deployment.ports) }} {{- $appPort := default dict (first .Values.deployment.ports) }} {{- /* 合并字典 */}} {{- $mergedPort := merge $appPort $commonPort }} {{- /* 合并顶层deployment配置,替换ports数组 */}} {{- $deployment := merge .Values.common.deployment .Values.deployment }} {{- $_ := set $deployment "ports" (list $mergedPort) }}
方案3:调整Values结构(可选)
如果允许修改values文件结构,将ports从数组改为单个字典,mergeDeep就能直接合并字段:
common/values.yaml:
deployment: port: name: http protocol: TCP
my-app/values.yaml:
deployment: port: containerPort: 8081
模板中合并并转为数组:
{{- $deployment := mergeDeep .Values.common.deployment .Values.deployment }}
使用时转为数组:
ports: - {{ toYaml $deployment.port | nindent 4 }}
内容的提问来源于stack exchange,提问作者Tapas Bose
相关产品推荐
相关产品推荐

