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:
Entry | Description | Equivalent to |
---|---|---|
@yearly (or @annually) | Run once a year at midnight of 1 January | 0 0 1 1 * |
@monthly | Run once a month at midnight of the first day of the month | 0 0 1 * * |
@weekly | Run once a week at midnight on Sunday morning | 0 0 * * 0 |
@daily (or @midnight) | Run once a day at midnight | 0 0 * * * |
@hourly | Run once an hour at the beginning of the hour | 0 * * * * |
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/