3.3. CronJobs and Jobs

Jobs are different from normal Deployments: Jobs execute a time-constrained operation and report the result as soon as they are finished; think of a batch job. To achieve this, a Job creates a Pod and runs a defined command. A Job isn’t limited to creating a single Pod, it can also create multiple Pods. When a Job is deleted, the Pods started (and stopped) by the Job are also deleted.

For example, a Job is used to ensure that a Pod is run until its completion. If a Pod fails, for example because of a Node error, the Job starts a new one. A Job can also be used to start multiple Pods in parallel.

More detailed information can be retrieved from the Kubernetes documentation .

Task 3.3.1: Create a Job for a database dump

We now want to create a dump of the running database, but without the need of interactively logging into the Pod.

Let’s first look at the Job resource that we want to create.

apiVersion: batch/v1
kind: Job
metadata:
  name: database-dump
spec:
  template:
    spec:
      containers:
      - name: mariadb
        image: mirror.gcr.io/mariadb:10.5
        command:
        - 'bash'
        - '-eo'
        - 'pipefail'
        - '-c'
        - >
          trap "echo Backup failed; exit 0" ERR;
          FILENAME=backup-${MYSQL_DATABASE}-`date +%Y-%m-%d_%H%M%S`.sql.gz;
          mysqldump --user=${MYSQL_USER} --password=${MYSQL_PASSWORD} --host=${MYSQL_HOST} --port=${MYSQL_PORT} --skip-lock-tables --quick --add-drop-database --routines ${MYSQL_DATABASE} | gzip > /tmp/$FILENAME;
          echo "";
          echo "Backup successful"; du -h /tmp/$FILENAME;          
        env:
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              key: database-name
              name: mariadb
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              key: database-user
              name: mariadb
        - name: MYSQL_HOST
          value: mariadb
        - name: MYSQL_PORT
          value: "3306"
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              key: database-password
              name: mariadb
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
          requests:
            cpu: 20m
            memory: 64Mi
      restartPolicy: Never

The parameter .spec.template.spec.containers[0].image shows that we use the same image as the running database. In contrast to the database Pod, we don’t start a database afterwards, but run a mysqldump command, specified with .spec.template.spec.containers[0].command. To perform the dump, we use the environment variables of the database deployment to set the hostname, user and password parameters of the mysqldump command. The MYSQL_PASSWORD variable refers to the value of the secret, which is already used for the database Pod. This way we ensure that the dump is performed with the same credentials.

Let’s create our Job: Create a file named job_database-dump.yaml with the content above and execute the following command:

kubectl apply -f ./job_database-dump.yaml --namespace <namespace>

Check if the Job was successful:

kubectl describe jobs/database-dump --namespace <namespace>

The executed Pod can be shown as follows:

kubectl get pods --namespace <namespace>

To show all Pods belonging to a Job in a human-readable format, the following command can be used:

kubectl get pods --selector=job-name=database-dump --output=go-template="{{range .items}}{{.metadata.name}}{{end}}" --namespace <namespace>

CronJobs

A CronJob is nothing else than a resource which creates a Job at a defined time, which in turn starts (as we saw in the previous section) a Pod to run a command. Typical use cases are cleanup Jobs, which tidy up old data for a running Pod, or a Job to regularly create and save a database dump as we just did during this lab.

The CronJob’s definition will remind you of the Deployment’s structure, or really any other control resource. There’s most importantly the schedule specification in cron schedule format , some more things you could define and then the Job’s definition itself that is going to be created by the CronJob:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-dump
spec:
  schedule: "5 4 * * *"
  concurrencyPolicy: "Replace"
  startingDeadlineSeconds: 200
  suspend: true
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: mariadb
            ...

Further information can be found in the Kubernetes CronJob documentation .