how can I iteratively create pods from list using Helm?

6/25/2018

I'm trying to create a number of pods from a yaml loop in helm. if I run with --debug --dry-run the output matches my expectations, but when I actually deploy to to a cluster, only the last iteration of the loop is present.

some yaml for you:

{{ if .Values.componentTests }}
{{- range .Values.componentTests }}
apiVersion: v1
kind: Pod
metadata:
  name: {{ . }}
  labels:
    app: {{ . }}
    chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
    release: {{ $.Release.Name }}
    heritage: {{ $.Release.Service }}
spec:
{{ toYaml $.Values.global.podSpec | indent 2 }}
  restartPolicy: Never
  containers:
  - name: {{ . }}
    ports:
      - containerPort: 3000
    image: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/{{ . }}:latest
    imagePullPolicy: Always
    command: ["sleep"]
    args: ["100d"]
    resources:
      requests:
        memory: 2000Mi
        cpu: 500m
{{- end }}
{{ end }}

when I run helm upgrade --install --set componentTests="{a,b,c}" --debug --dry-run

I get the following output:

# Source: <path-to-file>.yaml
apiVersion: v1
kind: Pod
metadata:
  name: a
  labels:
    app: a
    chart: integrationtests-0.0.1
    release: funny-ferret
    heritage: Tiller
spec: 
  restartPolicy: Never
  containers:
  - name: content-tests
    ports:
      - containerPort: 3000
    image: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/a:latest
    imagePullPolicy: Always
    command: ["sleep"]
    args: ["100d"]
    resources:
      requests:
        memory: 2000Mi
        cpu: 500m
apiVersion: v1
kind: Pod
metadata:
  name: b
  labels:
    app: b
    chart: integrationtests-0.0.1
    release: funny-ferret
    heritage: Tiller
spec:  
  restartPolicy: Never
  containers:
  - name: b
    ports:
      - containerPort: 3000
    image: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/b:latest
    imagePullPolicy: Always
    command: ["sleep"]
    args: ["100d"]
    resources:
      requests:
        memory: 2000Mi
        cpu: 500m
apiVersion: v1
kind: Pod
metadata:
  name: c
  labels:
    app: users-tests
    chart: integrationtests-0.0.1
    release: funny-ferret
    heritage: Tiller
spec:
  restartPolicy: Never
  containers:
  - name: c
    ports:
      - containerPort: 3000
    image: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/c:latest
    imagePullPolicy: Always
    command: ["sleep"]
    args: ["100d"]
    resources:
      requests:
        memory: 2000Mi
        cpu: 500m
---

(some parts have been edited/removed due to sensitivity/irrelevance)

which looks to me like I it does what I want it to, namely create a pod for a another for b and a third for c.

however, when actually installing this into a cluster, I always only end up with the pod corresponding to the last element in the list. (in this case, c) it's almost as if they overwrite each other, but given that they have different names I don't think they should? even running with --debug but not --dry-run the output tells me I should have 3 pods, but using kubectl get pods I can see only one.

How can I iteratively create pods from a list using Helm?

-- Anders Martini
kubernetes
kubernetes-helm
yaml

1 Answer

6/25/2018

found it!

so apparently, helm uses --- as a separator between specifications of pods/services/whatHaveYou.

specifying the same fields multiple times in a single chart is valid, it will use the last specified value for for any given field. To avoid overwriting values and instead have multiple pods created, simply add the separator at the end of the loop:

{{ if .Values.componentTests }}
{{- range .Values.componentTests }}
apiVersion: v1
kind: Pod
metadata:
  name: {{ . }}
  labels:
    app: {{ . }}
    chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
    release: {{ $.Release.Name }}
    heritage: {{ $.Release.Service }}
spec:
{{ toYaml $.Values.global.podSpec | indent 2 }}
  restartPolicy: Never
  containers:
  - name: {{ . }}
    ports:
      - containerPort: 3000
    image: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/{{ . }}:latest
    imagePullPolicy: Always
    command: ["sleep"]
    args: ["100d"]
    resources:
      requests:
        memory: 2000Mi
        cpu: 500m
---
{{- end }}
{{ end }}
-- Anders Martini
Source: StackOverflow