Technotes

Technotes for future me

Kubernetes cronjob

A CronJob starts one-time Jobs on a repeating schedule.

CronJob is meant for performing regular scheduled actions such as backups, report generation, and so on. One CronJob object is like one line of a crontab (cron table) file on a Unix system. It runs a Job periodically on a given schedule, written in Cron format.

CronJobs have limitations and idiosyncrasies. For example, in certain circumstances, a single CronJob can create multiple concurrent Jobs. See the limitations below.

When the control plane creates new Jobs and (indirectly) Pods for a CronJob, the .metadata.name of the CronJob is part of the basis for naming those Pods.

Example

This example CronJob manifest prints the current time and a hello message every minute:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

Writing a CronJob spec

Schedule syntax

The .spec.schedule field is required. The value of that field follows the Cron syntax:

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
# │ │ │ │ │                                   OR sun, mon, tue, wed, thu, fri, sat
# │ │ │ │ │ 
# │ │ │ │ │
# * * * * *

For example, 0 3 * * 1 means this task is scheduled to run weekly on a Monday at 3 AM.

Other than the standard syntax, some macros like @monthly can also be used:

EntryDescriptionEquivalent to
@yearly (or @annually)Run once a year at midnight of 1 January0 0 1 1 *
@monthlyRun once a month at midnight of the first day of the month0 0 1 * *
@weeklyRun once a week at midnight on Sunday morning0 0 * * 0
@daily (or @midnight)Run once a day at midnight0 0 * * *
@hourlyRun once an hour at the beginning of the hour0 * * * *

To generate CronJob schedule expressions, you can also use web tools like crontab.guru

Schedule suspension

You can suspend execution of Jobs for a CronJob, by setting the optional .spec.suspend field to true. The field defaults to false.

This setting does not affect Jobs that the CronJob has already started.

If you do set that field to true, all subsequent executions are suspended (they remain scheduled, but the CronJob controller does not start the Jobs to run the tasks) until you unsuspend the CronJob.

Caution:
Executions that are suspended during their scheduled time count as missed Jobs. When .spec.suspend changes from true to false on an existing CronJob without a starting deadline, the missed Jobs are scheduled immediately.

Jobs history limits

The .spec.successfulJobsHistoryLimit and .spec.failedJobsHistoryLimit fields specify how many completed and failed Jobs should be kept. Both fields are optional.

  • .spec.successfulJobsHistoryLimit : This field specifies the number of successful finished jobs to keep. The default value is 3. Setting this field to 0 will not keep any successful jobs.
  • .spec.failedJobsHistoryLimit : This field specifies the number of failed finished jobs to keep. The default value is 1. Setting this field to 0 will not keep any failed jobs.

For another way to clean up Jobs automatically, see Clean up finished Jobs automatically.

Time zones

FEATURE STATE: Kubernetes v1.27 [stable]

For CronJobs with no time zone specified, the kube-controller-manager interprets schedules relative to its local time zone.

You can specify a time zone for a CronJob by setting .spec.timeZone to the name of a valid time zone. For example, setting instructs Kubernetes to interpret the schedule relative to Coordinated Universal Time.

A time zone database from the Go standard library is included in the binaries and used as a fallback in case an external database is not available on the system

Examples

apiVersion: batch/v1
kind: CronJob
metadata:
  labels:
    app.kubernetes.io/instance: download-donderschoer
    app: record-donderschoer
  name: record-donderschoer-28-dec
  namespace: download-donderschoer
spec:
  schedule: "55 19 28 12 *"
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  timezone: Europe/Amsterdam
  jobTemplate:
    spec:
      template:
        metadata:
          labels:
            app: record-donderschoer
            app.kubernetes.io/instance: download-donderschoer
        spec:
          imagePullSecrets:
          - name: blaat
          containers:
          - name: record-donderschoer
            image: ghcr.io/adelerhof/record-donderschoer:2024-10-14
            resources:
              limits:
                memory: "512Mi"
                cpu: "500m"
              requests:
                memory: "256Mi"
                cpu: "250m"
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
              capabilities:
                drop:
                - ALL
              seccompProfile:
                type: RuntimeDefault
              runAsNonRoot: true
              runAsUser: 2000
              runAsGroup: 2000
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /www
              name: donderschoer-volume
          volumes:
            - name: donderschoer-volume
              persistentVolumeClaim:
                claimName: download-donderschoer-pvc
          restartPolicy: OnFailure
          automountServiceAccountToken: false

Nice to know

To see a list of cron jobs, run:

kubectl get cronjob

To see the Jobs created by the CronJob, run:

kubectl get jobs --watch

To view the logs from the pod to verify the command ran successfully:

kubectl logs -f <pod-name>

To clean up, delete the CronJob. Deleting the CronJob removes all the jobs and pods it created and stops it from creating additional jobs:

kubectl delete cronjob <name>

References

Source:

https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
https://crontab.guru/

Last updated on 19 Oct 2024
Published on 14 Oct 2024
Edit on GitHub