0

i have a helm deployment.yaml template file containing the below:

containers:
      {{- include "app.container" (merge .Values.app $) | nindent 8 }}
      {{- range $k, $v := .Values.extraContainers }}
      {{- $nameDict := dict "name" $k -}}
        {{- include "app.container" (mustMergeOverwrite $.Values.app $nameDict $v)  | nindent 8 }}
      {{- end }}

a values.yaml that looks like this:

The values under .Values.app are intended to be the values for the main container, but should also act as the defaults for the extraContainers when values are not specified explicitly for the extraContainers.

app:
  image:
    name: xxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/foobar
    tag: latest
  probes:
    readinessProbe:
      path: /_readiness
      enabled: true
    livenessProbe:
      path: /_liveness
      enabled: true
  port: 80
  resources:
    limits:
      cpu: 10Mi
      memory: 2Gi
    requests:
      cpu: 10Mi
      memory: 2Gi

extraContainers:
  extra-container1:
    image:
      name: xxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/foobar-extra
      tag: test
    command:
      - sleep
      - 10
    envVars:
      - name: FOO
        value: BAR
    port: 8080
    probes:
      readinessProbe:
        path: /extraContainerReadinessPath
        port: 8080
      livenessProbe:
        path: /extraContainerLivenessPath
        port: 8080
    resources:
      limits:
        cpu: 1000Mi
        memory: 1Gi
      requests:
        cpu: 1000Mi
        memory: 1Gi
  extra-container2:
    image:
      name: 211161777205.dkr.ecr.eu-west-1.amazonaws.com/foobar-two
      tag: latest
    command:
      - sleep
      - 10
    probes:
      readinessProbe:
        enabled: false
      livenessProbe:
        enabled: false

and a helper containing the below:

{{/*
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 }}
  env:
    {{- range .envVars }}
    - name: {{ .name }}
      {{- with .value }}
      value: {{ . | quote }}
      {{- end }}
      {{- with .valueFrom }}
      valueFrom:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    {{- end }}
{{- end -}}

{{/*
app container
*/}}
{{- define "app.container" -}}
{{- include "app.containerBase" . }}
  imagePullPolicy: {{ .image.pullPolicy | default "Always" }}
  {{- if .port }}
  ports:
    - containerPort: {{ .port }}
      protocol: {{ .protocol | upper }}
  {{- end }}
  {{- if .probes.readinessProbe.enabled }}
  readinessProbe:
    {{- if .probes.readinessProbe.custom }}
    {{- toYaml .probes.readinessProbe.custom | nindent 4 }}
    {{- else }}
    httpGet:
      port: {{ .probes.readinessProbe.port | default .port }}
      path: "{{ required "app.probes.readinessProbe.path is required" .probes.readinessProbe.path }}"
      scheme: HTTP
    initialDelaySeconds: {{ .probes.readinessProbe.initialDelaySeconds | default "40" }}
    periodSeconds: {{ .probes.readinessProbe.periodSeconds | default 10 }}
    timeoutSeconds: {{ .probes.readinessProbe.timeoutSeconds | default "30" }}
    successThreshold: {{ .probes.readinessProbe.successThreshold | default "3" }}
    failureThreshold: {{ .probes.readinessProbe.failureThreshold | default "2" }}
    {{- end }}
  {{- end }}
  {{- if .probes.livenessProbe.enabled }}
  livenessProbe:
  {{- if .probes.livenessProbe.custom }}
  {{- toYaml .probes.livenessProbe.custom | nindent 4 }}
  {{- else }}
    httpGet:
      port: {{ .probes.livenessProbe.port | default .port }}
      path: "{{ required "app.probes.livenessProbe.path is required" .probes.livenessProbe.path }}"
      scheme: HTTP
    initialDelaySeconds: {{ .probes.livenessProbe.initialDelaySeconds | default "40" }}
    periodSeconds: {{ .probes.livenessProbe.periodSeconds | default "10" }}
    timeoutSeconds: {{ .probes.livenessProbe.timeoutSeconds | default "30" }}
    successThreshold: {{ .probes.livenessProbe.successThreshold | default "1" }}
    failureThreshold: {{ .probes.livenessProbe.failureThreshold | default "2" }}
  {{- end }}
  {{- end }}
  {{- if .probes.startupProbe.enabled }}
  startupProbe:
  {{- if .probes.startupProbe.custom }}
  {{- toYaml .probes.startupProbe.custom | nindent 4 }}
  {{- else }}
    httpGet:
      port: {{ .probes.startupProbe.port | default .port }}
      path: "{{ required "app.probes.startupProbe.path is required" .probes.startupProbe.path }}"
      scheme: HTTP
    initialDelaySeconds: {{ .probes.startupProbe.initialDelaySeconds | default "40" }}
    periodSeconds: {{ .probes.startupProbe.periodSeconds | default "10" }}
    timeoutSeconds: {{ .probes.startupProbe.timeoutSeconds | default "30" }}
    successThreshold: {{ .probes.startupProbe.successThreshold | default "1" }}
    failureThreshold: {{ .probes.startupProbe.failureThreshold | default "2" }}
  {{- end }}
  {{- end }}
  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 }}
{{- end -}}

running helm template results in the below:

      containers:
        - name: app
          image: xxxxx.dkr.ecr.eu-west-1.amazonaws.com/foobar:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 80
              protocol: TCP
          readinessProbe:
            httpGet:
              port: 80
              path: "/_readiness"
              scheme: HTTP
            initialDelaySeconds: 40
            periodSeconds: 10
            timeoutSeconds: 30
            successThreshold: 3
            failureThreshold: 2
          livenessProbe:
            httpGet:
              port: 80
              path: "/_liveness"
              scheme: HTTP
            initialDelaySeconds: 40
            periodSeconds: 10
            timeoutSeconds: 30
            successThreshold: 1
            failureThreshold: 2
          resources:
            limits:
              cpu: "10Mi"
              memory: "2Gi"
            requests:
              cpu: "10Mi"
              memory: "2Gi"
        - name: extra-container1
          image: xxxx.dkr.ecr.eu-west-1.amazonaws.com/foobar-extra:test
          command:
            - "sleep"
            - "10"
          env:
            - name: FOO
              value: "BAR"
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          readinessProbe:
            httpGet:
              port: 8080
              path: "/extraContainerReadinessPath"
              scheme: HTTP
            initialDelaySeconds: 40
            periodSeconds: 10
            timeoutSeconds: 30
            successThreshold: 3
            failureThreshold: 2
          livenessProbe:
            httpGet:
              port: 8080
              path: "/extraContainerLivenessPath"
              scheme: HTTP
            initialDelaySeconds: 40
            periodSeconds: 10
            timeoutSeconds: 30
            successThreshold: 1
            failureThreshold: 2
          resources:
            limits:
              cpu: "1000Mi"
              memory: "1Gi"
            requests:
              cpu: "1000Mi"
              memory: "1Gi"
        - name: extra-container2
          image: xxxxx.dkr.ecr.eu-west-1.amazonaws.com/foobar-two:latest
          command:
            - "sleep"
            - "10"
          env:
            - name: FOO
              value: "BAR"
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: "1000Mi"
              memory: "1Gi"
            requests:
              cpu: "1000Mi"
              memory: "1Gi"

As you can see, extra-container2 should have the default resource limits/requests of 10Mi and 2Gi, but they seem to have the values from the previous iteration of the loop(extra-container1). The same occurs with the presence of the FOO=BAR env var present in extra-container2, although it is only set in extra-container1.

essentially it looks like values from the first loop in the range, are persisting into the second loop, when the second loop doesn't explicitly set those values.

thank you for reading

gurpsone
  • 463
  • 7
  • 17

0 Answers0