Helm Charts for Creating Kubernetes Cron Jobs

Pratik Saha
3 min readNov 24, 2021

--

What is a Cron Job?

A cron job runs “jobs” on a repeating schedule. What are these “jobs”? Jobs are a single or a set of tasks that runs until completion. These jobs can be many things, for example, taking backups, generating reports, sending emails, etc. A cronjob will ensure that these tasks run periodically and the period can be configured by users.

For more details on Kubernetes cron jobs, go to — https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/

Create a Single Kubernetes Cron Job

Firstly, we will look at how we can add a simple Kubernetes cron job with helm templates. We have a script that needs to run every 30 minutes and take backup, let’s say the script name is take_backup.py and it’s located in the/opt/service directory. We are also assuming that the script needs some configuration values to run which are stored in the /opt/service/service-config.json file, we are using Kubernetes configmap to mount application config to the appropriate path. Here is the helm template -

cron-job.yaml

apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: {{ .Values.cronjob.name }}
spec:
schedule: {{ .Values.cronjob.schedule | quote }}
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: ENV
value: {{ .Values.env }}
command:
- /bin/sh
- -c
- |
{{ .Values.cronjob.command }}
volumeMounts:
- name: service-config
mountPath: "/opt/service/service-config.json"
subPath: "service-config.json"
volumes:
- name: service-config
configMap:
name: {{ include "app.fullname" . }}-configmap
restartPolicy: OnFailure

The template of the cron job depends on the values.yaml file. The file will look like the following -

values.yaml

env: staging
image:
repository: my-image-repository
tag: 0.1
pullPolicy: IfNotPresent
cronjob:
name: take-backup
schedule: "*/30 * * * *"
command: /opt/service/take_backup.py

Single Cron Job Chart: https://github.com/pratikjoy7/helm-k8s-cronjob/tree/main/single-cron-job

Create Multiple Kubernetes Cron Jobs from a Single Chart

Let’s assume that after adding a script that takes backups every 30 minutes, you have accumulated a lot of backups. You don’t need so many backups and now want to add another script that will run every 7 days at 8 AM and clean up some old backup. You must be thinking that you need another file like cron-job.yaml to create a new cron job. You are correct, that can be one approach. But let me show you a better way. We will be using a single chart to create multiple cron jobs. First, we need to modify the values file we added previously.

values.yaml

env: staging
image:
repository: my-image-repository
tag: 0.1
pullPolicy: IfNotPresent
cronjobs:
- name: take-backup
schedule: "*/30 * * * *"
command: /opt/service/take_backup.py
- name: trim-backups
schedule: "0 8 * * 0"
command: /opt/service/trim_backups.py

We have replaced cronjob with a cronjobs list. Now, we need to modify the cron-job.yaml file to iterate over this list and create multiple cronjobs. For iterating over a list, we can use the range operator.

cron-job.yaml

{{- range $cronjob := .Values.cronjobs }}
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: {{ .name }}
spec:
schedule: {{ .schedule | quote }}
successfulJobsHistoryLimit: 10
failedJobsHistoryLimit: 10
jobTemplate:
spec:
template:
spec:
containers:
- name: {{ $.Chart.Name }}
image: {{ $.Values.image.repository }}:{{ $.Values.image.tag }}
imagePullPolicy: {{ $.Values.image.pullPolicy }}
env:
- name: ENV
value: {{ $.Values.env }}
command:
- /bin/sh
- -c
- |
{{ .command }}
volumeMounts:
- name: service-config
mountPath: "/opt/service/service-config.json"
subPath: "service-config.json"
volumes:
- name: service-config
configMap:
name: {{ include "app.fullname" $ }}-configmap
restartPolicy: OnFailure
{{- end -}}

Let’s look at the changes we have made in the cron-job.yaml file apart from adding the range operator. The range operator is iterating over the .Values.cronjobs list. On each iteration, the items directly available through the cronjob variable. So, we don’t need to explicitly define .Values.cronjob.name anymore, we can directly define .name, .schedule, and .command. Another thing to note is that we can not reference .Values anymore. If we do, helm will try to find a key called values in the cronjobs list. But we still need to access the root scope for fetching certain values. We can use the $ symbol to access the root scope. So, wherever we were passing or referencing the root scope, we will have to replace it with the $ symbol. For example, .Values will have to be replaced with $.Values.

Multiple Cron Jobs Chart: https://github.com/pratikjoy7/helm-k8s-cronjob/tree/main/multi-cron-job

--

--

Pratik Saha
Pratik Saha

Written by Pratik Saha

Manager, Software Engineering (DevOps) at Optimizely!

No responses yet