setting up multiple cronjob using helm
Asked Answered
A

3

4

I am trying to deploy multiple cronjob using same helm chart. I have defined cronjobs in values.yaml file which is below.

cronjob:
  crons:
    "0":
    name: one-minute-cron
    schedule: "*/1 * * * *"
    "1":
    name: five-minute-cron
    schedule: "*/5 * * * *"

  metadata:
    namespace: "{{K8S_NS}}"
    creationTimestamp: null

  restartPolicy: OnFailure

  image:
    repository: "{{CI_REGISTRY_IMAGE}}/{{CI_COMMIT_REF_SLUG}}:{{CI_COMMIT_SHA}}.{{CI_PIPELINE_IID}}"
    pullPolicy: "Always"
    imagePullSecrets: git-image-pull-secret-cron
    restartPolicy: OnFailure

  resources:
    requests:
      cpu: 1.0
      memory: "128Mi"
    limits:
      cpu: 2.0
      memory: "192Mi"

Below is my cronjob.yaml file from templates folder.

{{- range $job, $val := .Values.cronjob.crons }}
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  namespace: {{ $.Values.cronjob.metadata.namespace }}
spec:
  concurrencyPolicy: Allow
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      creationTimestamp: {{ $.Values.cronjob.metadata.creationTimestamp }}
      name: {{ $.Values.cronjob.crons.name }}
    spec:
      template:
        metadata:
          creationTimestamp: {{ $.Values.cronjob.metadata.creationTimestamp }}
        spec:
          containers:
          - image: {{ $.Values.cronjob.image.repository }}
            imagePullPolicy: {{ $.Values.cronjob.image.pullPolicy }}
            name: {{ $.Values.cronjob.crons.name }}
            resources:
              requests:
                memory: {{ $.Values.cronjob.resources.requests.memory }}
                cpu: {{ $.Values.cronjob.resources.requests.cpu }}
              limits:
                memory: {{ $.Values.cronjob.resources.limits.memory }}
                cpu: {{ $.Values.cronjob.resources.limits.cpu }}

          dnsPolicy: ClusterFirst
          restartPolicy: {{ $.Values.cronjob.image.restartPolicy }}
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          imagePullSecrets:
            - name: {{ $.Values.cronjob.image.imagePullSecrets }}
  schedule: {{ quote $.Values.cronjob.crons.schedule }}
  successfulJobsHistoryLimit: 3
  suspend: false
status: {}
---
{{- end }}

When I run this in CICD pipeline for deployment in gitlab it throws below error.

Error: UPGRADE FAILED: error validating "": error validating data: [ValidationError(CronJob.spec.jobTemplate.spec.template.spec.containers[0]): missing required field "name" in io.k8s.api.core.v1.Container, ValidationError(CronJob.spec): missing required field "schedule" in io.k8s.api.batch.v1beta1.CronJobSpec]

Note: I have copied the whole repository from gitlab except the sensitive information such as gitlab secrets, templates. I have checked the other blogs as well for this but none of them are helping to get these crons working. Github repo link is here

Arletha answered 14/9, 2021 at 7:41 Comment(4)
Which helm version are you using (helm version --short)?Discarnate
I am having below helm version. helm version --short v3.2.0+ge11b7ceArletha
Could you please explain in more details which exactly helm command is used by CI/CD? I tried to replicate your issue, but I got error that resource name may not be empty so I added name: field under metadata: and it seems to be working. Not fully correctly at all, because helm is not iterating cron.cronjobs and always using the first value, but it still different issue than yours.Discarnate
I also encountered the error of resource name may not be empty. CI/CD is using helm upgrade command. Also I am not able to iterate through these crons defined in the values file. I am new to this helm deployment. I can deploy the crons manually from command line.Arletha
O
4

First, I think that cronjob.crons should be an array. Try changing it to:

cronjob:
  crons:
    - id: "0"
      name: "one-minute-cron"
      schedule: "*/1 * * * *"
    - id: "1"
      name: five-minute-cron
      schedule: "*/5 * * * *"

Then you can iterate over "crons" via:

{{- range $cron := .Values.cronjob.crons }}

You can then access the "cron" fields like so:

...
imagePullPolicy: {{ $.Values.cronjob.image.pullPolicy }}
name: {{ $cron.name }}
Ozonide answered 14/9, 2021 at 8:30 Comment(7)
Hi@cecunami, After making the changes you suggested, I am getting below error helm.go:84: [debug] template: example-cron/templates/cronjob.yaml:37:22: executing "example-cron/templates/cronjob.yaml" at <$.Values.cronjob.crons.schedule>: can't evaluate field schedule in type interface {}Arletha
Hi @ShaileshSutar, You should be using: $cron.schedule not: $.Values.cronjob.crons.scheduleOzonide
Now I am getting following error --> Error: template: example-cron/templates/cronjob.yaml:8:19: executing "example-cron/templates/cronjob.yaml" at <.Release.Name>: nil pointer evaluating interface {}.Name Apologies. Don't want to irritate you.Arletha
@ShaileshSutar, have you managed to solve this issue in the end ?Isolecithal
@Isolecithal Currently I have managed this through a workaround. I have created 2 cronjob.yaml templates inside templates folder. Basically I hard coded the secrets specific to the job in cronjob-five-minutes.yaml file and cronjob-one-minute.yaml file.Arletha
If it works for you, you may consider posting it also as an answer.Isolecithal
@ShaileshSutar You should be using <$.Release.Name> rather than <.Release.Name> when you are inside the range.Agrippina
S
3

If anyone (like me) stumbles on this thread, here is a working example.

In the templates/cronbjob.yaml

{{- range $cron := .Values.cronjob.crons }}
apiVersion: batch/v1
kind: CronJob
spec:
  schedule: {{ $cron.schedule | quote }}
  successfulJobsHistoryLimit: 5

And the values.yaml

cronjob:
  repository: XXXX
  crons:
    "0":
      name: somename
      schedule: "*/10 * * * *"
    "1":
      name: someothername
      schedule: "*/2 * * * *"

Since the schedule field contains a * it will mess up the rendering without the | quote

Siqueiros answered 1/9, 2022 at 14:29 Comment(0)
E
0

I post this cause it took me way too long to figure out.

If anyone else get's the error Capturing deployment metadata failed with error: YAMLException: duplicated mapping key at line <someline>, column 1: apiVersion: batch/v1 in Azure Pipeline, be assured that your heml deploy did NOT work, but all you have to do is add three dashes before the end of your cronjob.yaml end, e.g in your cronjob.yaml:

{{- range $name,$cron := .Values.cronjob.crons }}
apiVersion: batch/v1
kind: CronJob
metadata:
  name: some-job-name-{{$name}}
spec:
  timeZone: 'Canada/Eastern'
  schedule: {{ $cron.schedule | toJson }}
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: {{ $fullName }}-{{$name}}
            image: curlimages/curl
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - {{ $cron.command }}
          restartPolicy: OnFailure
{{/* you need these three dashes below to avoid errors in pipeline */}}
---
{{- end}}          

then in the values.yaml and/or your values-<env>.yaml:

cronjob:
  crons:
    poll:
      command: "curl something"
      schedule: "*/5 * * * *"
    weekly:
      command: "curl something-else"
      schedule: "*/10 * * * *"
Ecumenicalism answered 20/2 at 16:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.