如何从Helm库Chart中修改数组内的容器元素?
Helm库Chart单容器配置直接修改方案
问题场景
我有一个供多部署共享的Helm库Chart,核心模板片段如下:
{{- define "mylibchart.template.tpl" -}} ... spec: securityContext: fsGroup: 300 containers: - image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" name: {{ .Chart.Name }} securityContext: runAsUser: 300 ... {{- end -}} {{- define "mylibchart.template" -}} {{- include "mylibchart.util.merge" (append . "mylibchart.template.tpl") -}} {{- end -}}
目前可以正常覆盖数组外的配置项(如spec.securityContext.fsGroup):
{{- include "mylibchart.template" (list . "foobar.deployment") -}} {{- define "foobar.deployment" -}} kind: Pod spec: securityContext: fsGroup: 333 {{- end -}}
但无法直接修改数组内的容器配置——直接定义containers数组会替换整个数组,而非修改单个容器:
{{- include "mylibchart.template" (list . "foobar.deployment") -}} {{- define "foobar.deployment" -}} kind: Pod spec: containers: - image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" securityContext: runAsUser: 333 {{- end -}}
库中仅包含一个容器,希望找到直接修改该容器配置的方案,避免用Values带来的冗余脚手架。
可行解决方案
1. 拆分容器为独立模板
将库中的容器配置拆成单独的模板片段,子Chart直接重写该片段即可修改容器配置。
修改库Chart模板:
{{- define "mylibchart.container" -}} image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" name: {{ .Chart.Name }} securityContext: runAsUser: 300 {{- end -}} {{- define "mylibchart.template.tpl" -}} ... spec: securityContext: fsGroup: 300 containers: - {{- include "mylibchart.container" . | nindent 6 }} ... {{- end -}} {{- define "mylibchart.template" -}} {{- include "mylibchart.util.merge" (append . "mylibchart.template.tpl") -}} {{- end -}}
子Chart中重写容器模板:
{{- include "mylibchart.template" . -}} {{- define "mylibchart.container" -}} image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" securityContext: runAsUser: 333 {{- end -}}
2. 自定义合并逻辑支持单元素数组合并
修改库中的mylibchart.util.merge函数,针对单元素数组做深度合并而非替换。
示例自定义合并逻辑:
{{- define "mylibchart.util.merge" -}} {{- $root := index . 0 -}} {{- $baseTpl := index . 1 -}} {{- $overrideTpl := index . 2 -}} {{- $base := fromYaml (include $baseTpl $root) -}} {{- $override := fromYaml (include $overrideTpl $root) | default dict -}} {{- /* 处理单元素containers数组的合并 */ -}} {{- if and (hasKey $base "spec") (hasKey $base.spec "containers") (eq (len $base.spec.containers) 1) -}} {{- if and (hasKey $override "spec") (hasKey $override.spec "containers") (eq (len $override.spec.containers) 1) -}} {{- $base.spec.containers = list (merge $base.spec.containers._0 $override.spec.containers._0) -}} {{- unset $override.spec "containers" -}} {{- end -}} {{- end -}} {{- merge $base $override | toYaml -}} {{- end -}}
修改后,原来的“非法”写法即可生效,合并逻辑会自动将传入的容器配置与原配置深度合并。
3. 模板内嵌入局部配置参数
在库模板中预留容器配置的合并入口,子Chart通过Values传递局部修改项(仅需修改时定义,无冗余)。
修改库模板:
{{- define "mylibchart.template.tpl" -}} {{- $containerOverride := .Values.containerOverride | default dict -}} ... spec: securityContext: fsGroup: 300 containers: - image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" name: {{ .Chart.Name }} securityContext: runAsUser: 300 {{- merge . $containerOverride | toYaml | nindent 6 }} ... {{- end -}}
子Chart的Values中仅添加需要修改的配置:
containerOverride: securityContext: runAsUser: 333
内容的提问来源于stack exchange,提问作者Kyle Dumouchelle
相关产品推荐
相关产品推荐

