Job resources run their pods immediately when you create the Job resource. But many batch jobs need to be run at a specific time in the future or repeatedly in the specified interval. In Linux- and UNIX-like operating systems, these jobs are better known as cron jobs. Kubernetes supports them, too.
A cron job in Kubernetes is configured by creating a CronJob
resource. The schedule for running the job is specified in the well-known cron format, so if you’re familiar with regular cron jobs, you’ll understand Kubernetes’ CronJobs in a matter of seconds.
At the configured time, Kubernetes will create a Job resource according to the Job template configured in the CronJob object. When the Job resource is created, one or more pod replicas will be created and started according to the Job’s pod template, as you learned in the previous section. There’s nothing more to it.
Structure of scheduling CronJob
Let us first understand the basics of cron job. You can get the structure of different fields in crontab in /etc/crontab
file:
# For details see man 4 crontabs # Example of job definition: # .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * user-name command to be executed
Here I have taken an example cron job to help you understand the different field of crontab:
0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
- The first section of a cron job, a 0 in this example, refers to the minute that the job will happen. Since 0 is used here, the minutes section is :00.
- The next section is the hour; 5 in this case. Therefore, we can gather so far that the command will be run at 5:00 a.m. (cron uses military time).
- The third section refers to the day of the month, but we have an asterisk (*) here. The asterisk, in this case, means that it doesn't matter what day of the month it is; just run it.
- The fourth section is another asterisk. In this example, it means we don't care which month it is. So far, we have a command we want to run at 5:00 a.m., regardless of the date.
- The fifth field is set to 1 in our example, and this field represents the day of the week. Since we have 1 here, it means that we want to run the command on Mondays. (Sunday would have been 0).
- Finally, the command that we want to execute is listed.
- If we put it all together, this line means we want to run the following command every Monday at 5:00 a.m:
Get details of CronJob in Kubernetes
First of all we need the KIND name for using the cron job with Kubernetes, so we can list the api-resources and look out for your Job KIND
[root@controller ~]# kubectl api-resources | grep -iE 'KIND|cron'
NAME SHORTNAMES APIGROUP NAMESPACED KIND
cronjobs cj batch true CronJob
So we know that our KIND is CronJob
, to get the apiVersion
value of the CronJob
type we can use:
~]# kubectl explain cronjob.spec KIND: CronJob VERSION: batch/v1beta1 ...
Alternatively you can also use:
~]# kubectl explain cronjob.spec.schedule KIND: CronJob VERSION: batch/v1beta1 FIELD: schedule DESCRIPTION: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
So we have the KIND
and apiVersion
value to create a cron job scheduler with Kubernetes.
Create CronJob in Kubernetes
Imagine you need to run the batch job from your previous example every 2 minutes. To do that, create a CronJob
resource with the following specification.
[root@controller ~]# cat pod-cronjob.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: pod-cronjob
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: pod-cronjob
image: busybox
args:
- /bin/sh
- -c
- date; echo hello from k8s cluster
restartPolicy: OnFailure
The highlighted section is the template for the Job resources that will be created by this CronJob where our defined task will run every 2 minutes.
Now to create a cronjob we use following command:
[root@controller ~]# kubectl create -f pod-cronjob.yml
cronjob.batch/pod-cronjob created
List available CronJob with Kubernetes
To get the list of available scheduled cron jobs with Kubernetes we will use:
[root@controller ~]# kubectl get cronjobs.batch
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
pod-cronjob */2 * * * * False 0 20s
Monitor status of CronJob in Kubernetes
Job resources will be created from the CronJob
resource at approximately the scheduled time. The Job then creates the pods. Once a cronjob is started, you can first use kubectl get cronjobs.batch
to list the available cron jobs. Now when the job is planned to be executed then you can use following command to get the LIVE runtime status:
[root@controller ~]# kubectl get jobs --watch
NAME COMPLETIONS DURATION AGE
pod-cronjob-1606577040 0/1 0s
pod-cronjob-1606577040 0/1 0s 0s
Here as you see the first planned cronjob has started, you can get more details using following command where you can see that a new job pod-cronjob-1606577040-tnnb5
is started with current status as ContainerCreating
:
[root@controller ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 1 9h 10.44.0.1 worker-2.example.com <none> <none>
nginx-lab 1/1 Running 1 9h 10.44.0.2 worker-2.example.com <none> <none>
pod-add-settime-capability 1/1 Running 1 8h 10.44.0.4 worker-2.example.com <none> <none>
pod-as-user-guest 1/1 Running 1 8h 10.44.0.3 worker-2.example.com <none> <none>
pod-cronjob-1606577040-tnnb5 0/1 ContainerCreating 0 7s <none> worker-1.example.com <none> <none>
pod-drop-chown-capability 1/1 Running 1 7h50m 10.44.0.5 worker-2.example.com <none> <none>
pod-privileged 1/1 Running 1 8h 10.36.0.3 worker-1.example.com <none> <none>
In few seconds once the JOB is complete, you can see that the status of the respective job is shown as completed:
[root@controller ~]# kubectl get jobs --watch NAME COMPLETIONS DURATION AGE pod-cronjob-1606577040 1/1 12s 12s
Now similarly another job will start in another 2 minutes as planned in our kubernetes job scheduler:
[root@controller ~]# kubectl get jobs --watch
NAME COMPLETIONS DURATION AGE
pod-cronjob-1606577040 1/1 12s 109s
pod-cronjob-1606577160 0/1 0s
pod-cronjob-1606577160 0/1 0s 0s
In some time once the job is executed, then the status should be again shown as completed for the respective Pod:
[root@controller ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 1 9h
nginx-lab 1/1 Running 1 9h
pod-add-settime-capability 1/1 Running 1 8h
pod-as-user-guest 1/1 Running 1 8h
pod-cronjob-1606577040-tnnb5 0/1 Completed 0 2m16s
pod-cronjob-1606577160-75xbm 0/1 Completed 0 15s
pod-drop-chown-capability 1/1 Running 1 7h52m
Delete Kubernetes Cron Job
To delete your cron job you can execute following syntax:
~]# kubectl delete cronjobs.batch <cron_job_name>
For example to delete our cron job here:
[root@controller ~]# kubectl delete cronjobs.batch pod-cronjob
cronjob.batch "pod-cronjob" deleted
Conclusion
In this Kubernetes Tutorial we learned about Kubernetes job scheduler for jobs that need to run sometime in the future can be created through CronJob resources. In normal circumstances, a CronJob always creates only a single Job for each execution configured in the schedule, but it may happen that two Jobs are created at the same time, or none at all. To combat the first problem, your jobs should be idempotent (running them multiple times instead of once shouldn’t lead to unwanted results). For the second problem, make sure that the next job run performs any work that should have been done by the previous (missed) run.