Search code examples
kubernetes-helm

Helm: Passing array values through --set


i have a cronjob helm chat, i can define many jobs in values.yaml and cronjob.yaml will provision my jobs. I have faced an issue when setting the image tag id in command line, following command throw no errors but it wont update jobs image tag to new one.

helm upgrade cronjobs cronjobs/ --wait --set job.myservice.image.tag=b70d744

cronjobs will run with old image tag how can i resolve this?

here is my cronjobs.yaml

{{- $chart_name := .Chart.Name }}
{{- $chart_version := .Chart.Version | replace "+" "_" }}
{{- $release_name := .Release.Name }}

{{- range $job := .Values.jobs }}
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  namespace: "{{ $job.namespace }}"
  name: "{{ $release_name }}-{{ $job.name }}"
  labels:
    chart: "{{ $chart_name }}-{{ $chart_version }}"
spec:
  concurrencyPolicy: {{ $job.concurrencyPolicy }}
  failedJobsHistoryLimit: {{ $job.failedJobsHistoryLimit }}
  suspend: {{ $job.suspend }}
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: {{ $release_name }}
            cron: {{ $job.name }}
        spec:
          containers:
          - image: "{{ $job.image.repository }}:{{ $job.image.tag }}"
            imagePullPolicy: {{ $job.image.imagePullPolicy }}
            ports:
              - name: http
                containerPort: 80
                protocol: TCP
            name: {{ $job.name }}
            args:
{{ toYaml $job.args | indent 12 }}
            env:
{{ toYaml $job.image.env | indent 12 }}
            volumeMounts:
            - name: nfs
              mountPath: "{{ $job.image.nfslogpath }}"
          restartPolicy: OnFailure
          imagePullSecrets:
            - name: {{ $job.image.secret }}
          volumes:
            - name: nfs
              nfs:
                server: "{{ $job.image.server }}"
                path: "{{ $job.image.nfspath }}"
                readOnly: false
  schedule: {{ $job.schedule | quote }}
  successfulJobsHistoryLimit: {{ $job.successfulJobsHistoryLimit }}
  {{- end }}

here is my values.yaml

jobs:
  - name: myservice
    namespace: default
    image:
      repository: xxx.com/myservice
      tag: fe4544
      pullPolicy: Always
      secret: xxx
      nfslogpath: "/var/logs/"
      nfsserver: "xxx"
      nfspath: "/nfs/xxx/cronjobs/"
      nfsreadonly: false
      env:
    schedule: "*/5 * * * *"
    args:
    failedJobsHistoryLimit: 1
    successfulJobsHistoryLimit: 3
    concurrencyPolicy: Forbid
    suspend: false

  - name: myservice2
    namespace: default
    image:
      repository: xxxx/myservice2
      tag: 1dff39a
      pullPolicy: IfNotPresent
      secret: xxxx
      nfslogpath: "/var/logs/"
      nfsserver: "xxxx"
      nfspath: "/nfs/xxx/cronjobs/"
      nfsreadonly: false
      env:
    schedule: "*/30 * * * *"
    args:
    failedJobsHistoryLimit: 1
    successfulJobsHistoryLimit: 2
    concurrencyPolicy: Forbid
    suspend: false

Solution

  • Since you are using array in your values.yaml file, please see related issue

    Alternative solution

    • Your values.yaml is missing values for args and env. I've set them in my example, as well as changed indent to 14

    • Your cronjob.yaml server: "{{ $job.image.server }}" value is null, and I've changed it to .image.nfsserver

    Instead of using array, just separate your services like in example below:

    values.yaml

    jobs:
      myservice:
        namespace: default
        image:
          repository: xxx.com/myservice
          tag: fe4544
          pullPolicy: Always
          secret: xxx
          nfslogpath: "/var/logs/"
          nfsserver: "xxx"
          nfspath: "/nfs/xxx/cronjobs/"
          nfsreadonly: false
          env:
            key: val
        schedule: "*/5 * * * *"
        args:
          key: val
        failedJobsHistoryLimit: 1
        successfulJobsHistoryLimit: 3
        concurrencyPolicy: Forbid
        suspend: false
    
      myservice2:
        namespace: default
        image:
          repository: xxxx/myservice2
          tag: 1dff39a
          pullPolicy: IfNotPresent
          secret: xxxx
          nfslogpath: "/var/logs/"
          nfsserver: "xxxx"
          nfspath: "/nfs/xxx/cronjobs/"
          nfsreadonly: false
          env:
            key: val
        schedule: "*/30 * * * *"
        args:
          key: val
        failedJobsHistoryLimit: 1
        successfulJobsHistoryLimit: 2
        concurrencyPolicy: Forbid
        suspend: false
    

    In your cronjob.yaml use {{- range $job, $val := .Values.jobs }} to iterate over values.

    Use $job where you used {{ $job.name }}.

    Access values like suspend with {{ .suspend }} instead of {{ $job.suspend }}

    cronjob.yaml

    {{- $chart_name := .Chart.Name }}
    {{- $chart_version := .Chart.Version | replace "+" "_" }}
    {{- $release_name := .Release.Name }}
    
    {{- range $job, $val := .Values.jobs }}
    ---
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      namespace: {{ .namespace }} 
      name: "{{ $release_name }}-{{ $job }}"
      labels:
        chart: "{{ $chart_name }}-{{ $chart_version }}"
    spec:
      concurrencyPolicy: {{ .concurrencyPolicy }}
      failedJobsHistoryLimit: {{ .failedJobsHistoryLimit }}
      suspend: {{ .suspend }}
      jobTemplate:
        spec:
          template:
            metadata:
              labels:
                app: {{ $release_name }}
                cron: {{ $job }}
            spec:
              containers:
              - image: "{{ .image.repository }}:{{ .image.tag }}"
                imagePullPolicy: {{ .image.imagePullPolicy }}
                ports:
                  - name: http
                    containerPort: 80
                    protocol: TCP
                name: {{ $job }}
                args:
    {{ toYaml .args | indent 14 }}
                env:
    {{ toYaml .image.env | indent 14 }}
                volumeMounts:
                - name: nfs
                  mountPath: "{{ .image.nfslogpath }}"
              restartPolicy: OnFailure
              imagePullSecrets:
                - name: {{ .image.secret }}
              volumes:
                - name: nfs
                  nfs:
                    server: "{{ .image.nfsserver }}"
                    path: "{{ .image.nfspath }}"
                    readOnly: false
      schedule: {{ .schedule | quote }}
      successfulJobsHistoryLimit: {{ .successfulJobsHistoryLimit }}
    {{- end }}
    

    Passing values using --set :

    helm upgrade cronjobs cronjobs/ --wait --set jobs.myservice.image.tag=b70d744

    Example:

    helm install --debug --dry-run --set jobs.myservice.image.tag=my123tag .

    ...
    HOOKS:
    MANIFEST:
    
    ---
    # Source: foo/templates/cronjob.yaml
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      namespace: default
      name: "illmannered-iguana-myservice"
      labels:
        chart: "foo-0.1.0"
    spec:
      concurrencyPolicy: Forbid
      failedJobsHistoryLimit: 1
      suspend: false
      jobTemplate:
        spec:
          template:
            metadata:
              labels:
                app: illmannered-iguana
                cron: myservice
            spec:
              containers:
              - image: "xxx.com/myservice:my123tag"
                imagePullPolicy:
                ports:
                  - name: http
                    containerPort: 80
                    protocol: TCP
                name: myservice
                args:
                  key: val
    
                env:
                  key: val
    
                volumeMounts:
                - name: nfs
                  mountPath: "/var/logs/"
              restartPolicy: OnFailure
              imagePullSecrets:
                - name: xxx
              volumes:
                - name: nfs
                  nfs:
                    server: "xxx"
                    path: "/nfs/xxx/cronjobs/"
                    readOnly: false
      schedule: "*/5 * * * *"
      successfulJobsHistoryLimit: 3
    ---
    # Source: foo/templates/cronjob.yaml
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      namespace: default
      name: "illmannered-iguana-myservice2"
      labels:
        chart: "foo-0.1.0"
    spec:
      concurrencyPolicy: Forbid
      failedJobsHistoryLimit: 1
      suspend: false
      jobTemplate:
        spec:
          template:
            metadata:
              labels:
                app: illmannered-iguana
                cron: myservice2
            spec:
              containers:
              - image: "xxxx/myservice2:1dff39a"
                imagePullPolicy:
                ports:
                  - name: http
                    containerPort: 80
                    protocol: TCP
                name: myservice2
                args:
                  key: val
    
                env:
                  key: val
    
                volumeMounts:
                - name: nfs
                  mountPath: "/var/logs/"
              restartPolicy: OnFailure
              imagePullSecrets:
                - name: xxxx
              volumes:
                - name: nfs
                  nfs:
                    server: "xxxx"
                    path: "/nfs/xxx/cronjobs/"
                    readOnly: false
      schedule: "*/30 * * * *"
      successfulJobsHistoryLimit: 2
    

    Hope that helps!