英文:
Passing values to include function inside range, using defaults with merge
问题
根据您提供的YAML文件,问题在于您的Helm模板逻辑和值的处理方式。特别是在extraContainers
的循环中,当您定义了某些值后,这些值会在后续迭代中保留,除非您明确覆盖它们。这是因为Helm模板默认采用逐层覆盖的方式,而不是合并。
要实现您所期望的行为,您可以采取以下步骤:
- 修改您的
values.yaml
文件,将extraContainers
的资源值设置为nil
,以便在后续迭代中不继承之前的值。如下所示:
extraContainers:
extra-container2:
image:
name: xxx.dkr.ecr.eu-west-1.amazonaws.com/foobar-two
tag: test
# 将资源设置为nil
resources: nil
command:
- sleep
- 10
envVars:
- name: FOO
value: BAR
probes:
readinessProbe:
path: /ContainerTwoReadinessPath
livenessProbe:
path: /ContainerTwoLivenessPath
extra-container3:
image:
name: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar-three
tag: latest
# 将资源设置为nil
resources: nil
command:
- sleep
- 10
envVars:
- name: FOO
value: BAZ
probes:
readinessProbe:
enabled: false
livenessProbe:
enabled: false
- 在您的
deployment.yaml
模板中,确保在循环中检查资源是否为nil
,如果为nil
,则使用默认值。如下所示:
{{- range $k, $v := .Values.extraContainers }}
{{- $nameDict := dict "name" $k -}}
{{- include "app.container" (mustMergeOverwrite $.Values.app $nameDict $v) | nindent 8 }}
{{- include "ports" (merge $nameDict $v ) | nindent 8 }}
{{- with $v.resources }}
resources:
limits:
cpu: {{ .limits.cpu | default .cpu | quote }}
memory: {{ .limits.memory | default .memory | quote }}
requests:
cpu: {{ .requests.cpu | default .cpu | quote }}
memory: {{ .requests.memory | default .memory | quote }}
{{- end }}
{{- end }}
通过将资源设置为nil
,您可以确保extra-container3
不会继承来自extra-container2
的资源值,并且会使用默认的.values.app
中的资源值。
英文:
Given this deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
revisionHistoryLimit: 5
template:
spec:
containers:
{{- include "app.container" (merge .Values.app $) | nindent 8 }}
{{- include "ports" (merge .Values.app ) | nindent 8 }}
{{- range $k, $v := .Values.extraContainers }}
{{- $nameDict := dict "name" $k -}}
{{- include "app.container" (mustMergeOverwrite $.Values.app $nameDict $v) | nindent 8 }}
{{- include "ports" (merge $nameDict $v ) | nindent 8 }}
{{- end }}
This helpers file...
{{/* vim: set filetype=helm: */}}
{{/*
app container base
*/}}
{{- define "app.containerBase" -}}
- name: {{ .name | default "app" }}
image: {{ .image.name }}:{{ .image.tag }}
{{- if .command }}
command:
{{- range .command }}
- {{ . | quote }}
{{- end }}
{{- end }}
{{- if .args }}
args:
{{- range .args }}
- {{ . | quote }}
{{- end }}
{{- end }}
{{- range .envVars }}
- name: {{ .name }}
{{- with .value }}
value: {{ . | quote }}
{{- end }}
{{- with .valueFrom }}
valueFrom:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- if or .Values.configMaps .Values.secrets .Values.configMapRef }}
envFrom:
{{- if .Values.configMaps }}
- configMapRef:
name: "{{- include "app.fullname" $ }}"
{{- end }}
{{- range .Values.configMapRef }}
- configMapRef:
name: {{ . }}
{{- end }}
{{- range $name, $idk := $.Values.secrets }}
- secretRef:
name: "{{- include "app.fullname" $ }}-{{ $name }}"
{{- end }}
{{- end }}
{{- end -}}
{{/*
app container
*/}}
{{- define "app.container" -}}
{{- include "app.containerBase" . }}
resources:
limits:
cpu: {{ .resources.limits.cpu | default "100m" | quote }}
memory: {{ .resources.limits.memory | default "128Mi" | quote }}
{{- if .resources.limits.ephemeralStorage }}
ephemeral-storage: {{ .resources.limits.ephemeralStorage }}
{{- end }}
requests:
cpu: {{ .resources.requests.cpu | default "100m" | quote }}
memory: {{ .resources.requests.memory | default "128Mi" | quote }}
{{- if .resources.requests.ephemeralStorage }}
ephemeral-storage: {{ .resources.requests.ephemeralStorage }}
{{- end }}
securityContext:
runAsNonRoot: true
runAsUser: {{ .securityContext.runAsUser }}
runAsGroup: {{ .securityContext.runAsGroup }}
allowPrivilegeEscalation: false
{{- end -}}
{{/*
ports
*/}}
{{- define "ports" -}}
{{- if .port }}
ports:
- containerPort: {{ .port }}
protocol: {{ .protocol | default "tcp" | upper }}
{{- range .extraPorts}}
- containerPort: {{ required ".port is required." .port }}
{{- if .name }}
name: {{ .name }}
{{- end }}
{{- if .protocol }}
protocol: {{ .protocol | upper }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
This values.yaml
extraContainers:
extra-container2:
image:
name: xxx.dkr.ecr.eu-west-1.amazonaws.com/foobar-two
tag: test
command:
- sleep
- 10
envVars:
- name: FOO
value: BAR
probes:
readinessProbe:
path: /ContainerTwoReadinessPath
livenessProbe:
path: /ContainerTwoLivenessPath
resources:
limits:
cpu: 200Mi
memory: 2Gi
requests:
cpu: 200Mi
memory: 2Gi
extra-container3:
image:
name: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar-three
tag: latest
command:
- sleep
- 10
envVars:
- name: FOO
value: BAZ
probes:
readinessProbe:
enabled: false
livenessProbe:
enabled: false
app:
image:
name: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar
tag: latest
probes:
readinessProbe:
path: /_readiness
enabled: true
livenessProbe:
path: /_liveness
enabled: true
port: 100
resources:
limits:
cpu: 100Mi
memory: 1Gi
requests:
cpu: 100Mi
memory: 1Gi
Why does helm template
result in the below:
---
# Source: corp-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
revisionHistoryLimit: 5
template:
spec:
containers:
- name: app
image: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar:latest
resources:
limits:
cpu: "100Mi"
memory: "1Gi"
requests:
cpu: "100Mi"
memory: "1Gi"
securityContext:
runAsNonRoot: true
runAsUser: 2000
runAsGroup: 2000
allowPrivilegeEscalation: false
ports:
- containerPort: 100
protocol: TCP
- name: extra-container2
image: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar-two:test
command:
- "sleep"
- "10"
- name: FOO
value: "BAR"
resources:
limits:
cpu: "200Mi"
memory: "2Gi"
requests:
cpu: "200Mi"
memory: "2Gi"
securityContext:
runAsNonRoot: true
runAsUser: 2000
runAsGroup: 2000
allowPrivilegeEscalation: false
- name: extra-container3
image: xx.dkr.ecr.eu-west-1.amazonaws.com/foobar-three:latest
command:
- "sleep"
- "10"
- name: FOO
value: "BAZ"
resources:
limits:
cpu: "200Mi"
memory: "2Gi"
requests:
cpu: "200Mi"
memory: "2Gi"
securityContext:
runAsNonRoot: true
runAsUser: 2000
runAsGroup: 2000
allowPrivilegeEscalation: false
i.e why does extra-container3
have resources:
set with values from extra-container2
instead of taking them from the default set of resources found under .values.app
.
essentially, i want extracontainers
to use default values from .values.app
unless i explicitly set them inside the extracontainers
section. however it seems that if a previous iteration of the loop over extracontainers
defines some values, they are used in the next iteration if they are not overriden.
the resources for extra-container3 i am expecting are:
resources:
limits:
cpu: 100Mi
memory: 1Gi
requests:
cpu: 100Mi
memory: 1Gi
what am i doing wrong?
答案1
得分: 3
所以这里涉及到了一些事情,但大多数情况下答案是 `(mergeMustOverwrite)` **改变** 了 `$dest` 映射,这会导致你的范围“记住”了它所看到的最后一个值,根据你的问题,这并不是你想要的行为。最简单的答案是将 `(deepCopy $.Values.app)` 用作 `$dest`,但由于我们稍后将要讨论的另一个错误,这里有一个星号。
你看,`(deepCopy $.Values.app)` 会因为你莫名其妙地使用了 `(merge .Values.app $)` 而在 `helm` 中导致堆栈溢出,它会引入 `Chart`、`Files`、`Capabilities` 和整个世界。我猜想你的 `_helpers.tpl` 必须是从别处复制粘贴过来的,这解释了在 `define` 中错误的相对 `.Values` 引用。修复的一种方式是移除 `.Values.configMaps`,这样它将跟踪 `.app` 上下文,就像我猜测你想要的那样,或者你可以将第一个 `(merge)` 更改为人为地创建一个 `"Values": {}` 项,只是为了在尝试引用 `.app.Values.configMaps` 时防止模板崩溃。正确的方法将取决于你的意图,但 `(merge .Values.app $)` 几乎肯定不是它。
所以,要么:
```diff
--- a/templates/_helpers.tpl
+++ b/templates/_helpers.tpl
@@ -28,13 +28,13 @@ app container base
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
- {{- if or .Values.configMaps .Values.secrets .Values.configMapRef }}
+ {{- if or .configMaps .secrets .configMapRef }}
envFrom:
- {{- if .Values.configMaps }}
+ {{- if .configMaps }}
- configMapRef:
name: "{{- include "app.fullname" $ }}"
{{- end }}
- {{- range .Values.configMapRef }}
+ {{- range .configMapRef }}
- configMapRef:
name: {{ . }}
{{- end }}
或者:
containers:
- {{- include "app.container" (merge .Values.app $) | nindent 8 }}
+ {{- include "app.container" (merge .Values.app (dict "Values" (dict))) | nindent 8 }}
{{- include "ports" (merge .Values.app ) | nindent 8 }}
<details>
<summary>英文:</summary>
So there are a couple of things going on here, but mostly the answer is that `(mergeMustOverwrite)` **mutates** the `$dest` map, which causes your range to "remember" the last value it saw, which according to your question isn't the behavior you want. The simplest answer is to use `(deepCopy $.Values.app)` as the `$dest`, but there's an asterisk to that due to another bug we'll cover in a second
```diff
{{- $nameDict := dict "name" $k -}}
- {{- include "app.container" (mustMergeOverwrite $.Values.app $nameDict $v) | nindent 8 }}
+ {{- include "app.container" (mustMergeOverwrite (deepCopy $.Values.app) $nameDict $v) | nindent 8 }}
{{- include "ports" (merge $nameDict $v ) | nindent 8 }}
{{- end }}
You see, (deepCopy $.Values.app)
stack-overflows helm
because of your inexplicable use of (merge .Values.app $)
drags in Chart
, Files
, Capabilities
and the whole world. I'm guessing your _helpers.tpl
must have been copy-pasted from somewhere else, which explains the erroneous relative .Values
reference inside that define
. One way to fix that is to remove the .Values.configMaps
, so it will track the .app
context like I expect you meant, or you can change the first (merge)
to artificially create a "Values": {}
item just to keep the template from blowing up when in tries to reference .app.Values.configMaps
. The correct one will depend on what you were intending, but (merge .Values.app $)
is almost certainly not it
so, either:
--- a/templates/_helpers.tpl
+++ b/templates/_helpers.tpl
@@ -28,13 +28,13 @@ app container base
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
- {{- if or .Values.configMaps .Values.secrets .Values.configMapRef }}
+ {{- if or .configMaps .secrets .configMapRef }}
envFrom:
- {{- if .Values.configMaps }}
+ {{- if .configMaps }}
- configMapRef:
name: "{{- include "app.fullname" $ }}"
{{- end }}
- {{- range .Values.configMapRef }}
+ {{- range .configMapRef }}
- configMapRef:
name: {{ . }}
{{- end }}
or
containers:
- {{- include "app.container" (merge .Values.app $) | nindent 8 }}
+ {{- include "app.container" (merge .Values.app (dict "Values" (dict))) | nindent 8 }}
{{- include "ports" (merge .Values.app ) | nindent 8 }}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论