Kubernetes CronJobs — Part 1: Basics

By Alwyn Botha, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

Kubernetes cron jobs are used to define cron jobs.

From https://en.wikipedia.org/wiki/Cron

Use cron to schedule jobs (commands or shell scripts) to run periodically at fixed times, dates, or intervals.

It typically automates system maintenance or administration — though its general-purpose nature makes it useful for things like downloading files from the Internet and downloading email at regular intervals.

Cron is most suitable for scheduling repetitive tasks.

Kubernetes cron jobs have the features of Linux cron jobs, plus a few unique features of its own.

Part 1 introduces you to Kubernetes cron job basics plus some of these unique features.

1) Basic Cron Job Example

15 lines below you will find our most basic cron job YAML spec:

kind: CronJob for cron jobs.

Note the schedule: /1 *

It specifies when this cron job must run. Time syntax identical to what are used to on Linux systems.

Our basic cron job will run every minute.

schedule fields: minute hour day-of-month month day-of-week

*/1 … means every minute

Rest of fields: every hour, every day, every day-of-month, every month, every day-of-week

If you run man crontab in your terminal you will get comprehensive detail about the crontab time formats allowed.

( All cron jobs in this tutorial run every minute so that we can experiment with all cron job functionality as quickly as possible. It also runs every day, …. and so on so that anyone that runs it will get a running cron job ANY day of the year )

concurrencyPolicy: Allow is the default — we will learn and experiment with this later.

The rest of the YAML spec content is identical for a Pod.

Create the cron job:

Unfortunately Linux cron job functionality allows per minute as smallest time increments.

So throughout this tutorial we have to repeatedly wait around a minute before something happens.

You can use the date command repeately to peek as to when the seconds digits will be 00 — on those 00s cron job starts our cron jobs in this tutorial.

Alternatively use

  • kubectl get job
  • kubectl get pods

repeatedly until you see some action.

kubectl get cronjob provides a summary overview. Most of the time it is quite useless ( since there is no detail … and summary detail that would have been cool to have, is not there ).

After around a minute:

These 2 commands show different details. In this tutorial we will always use both these commands to learn when which helps most.

kubectl get job shows the JOB has been running 4s. COMPLETIONS is zero … it is still running.

kubectl get po shows we have one READY ( Running ) Pod … been running 5s.

Note jobs get prefixed with our cron job name ( from YAML spec )

Note Pods for that job get prefixed with our cron job name ( in YAML spec ) + 5 character hash ( random characters ).

Mere seconds later.

Job only had to sleep 5 seconds.

Using the combined information from both commands:

  • job has completed: COMPLETIONS 1
  • job took 6s … DURATION
  • Pod is Completed
  • Pod is no longer available … READY is 0

This is the look of a successfully ran cron job.

More information :

We will use SUSPEND later.

ACTIVE 0 … no Pods currently busy processing work for this cron job.

We saw moments ago our Pod slept 5 seconds and is now completed. For the rest of the minute the ACTIVE column will stay zero. It is awaiting the next precise minute to start another run of this cron job.

You will see around 30 cron job runs in this tutorial … understanding will emerge.

Nearly a minute later … all that happened is AGE increased … awaiting the next precise minute to start another run of this cron job.

30 seconds later.

Active is ONE. A Pod for this cron job is running.

We see our completed job listed first and new running job listed second — hint — look at AGE.

We see our completed POD first and new running POD last — hint — look at AGE.

10 seconds later: the second job and Pod are completed. ( It only had to sleep 5 seconds )

No new job is running — awaits next scheduled minute.

Another way to gather information about our cron job : ( irrelevant fields hidden )

In events we see a new job created every minute.

We also see the … Saw completed job: … around 10 seconds after it started.

After 3 minutes we have 3 completed jobs and Pods.

Seconds later, we JUST caught the creation of Pod number four.

This specific output makes it VERY easy to see in AGE … one new Pod every minute.

It would have been great if this command also showed:

  • number of jobs successfully completed
  • number of jobs UNsuccessfully completed

Introduction example complete. Delete job:

This deletes the job, all the Pods that ran under its management and all their job logs.

2) concurrencyPolicy: Allow

From https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#concurrency-policy

It specifies how to treat concurrent executions of a job that is created by this cron job.

Allow (default): The cron job allows concurrently running jobs

Our previous example was kept simple. Sleep for 5 seconds.

The concurrencyPolicy was irrelevant in its case: no two jobs / Pods were ever able to run simultaneously.

This example will demonstrate concurrencyPolicy in action.

Every minute a new job must run.

Our Pod must sleep for 90 seconds.

So after 60 seconds — when Pod still has 30 seconds of sleeping work left — another Pod will be automatically scheduled.

concurrencyPolicy: Allow will allow this existing Pod to continue running for the full 90 seconds.

The policy will also allow the simultaneous starting and running of the second newly scheduled Pod.


Nothing informative.

Many seconds later, first Pod starts:

Important … see below: One minute later, new Pod starts up, and old one continues to run.

Note the old job is still running, its COMPLETIONS is still zero.

The old pod is also READY … it is still running.

Two jobs, each with one Pod is running simultaneously.

After 90 seconds total runtime.

Above: first job is complete, second job is running.

Below: after several minutes: one job started every minute.

First 3 jobs show COMPLETIONS equal to 1 ( success ). DURATION correct for completed jobs.

History of completed Pods.

3 completed pods are no READY anymore. ( Completed successfully )

One pod has been running 61 seconds and is still ready. It still has 29 seconds of sleeping to do.

Our cron job precise minute timer kicked off another Pod that is still in preliminary ContainerCreating state.

Reference : https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits

By default 3 successfully done jobs are kept.

Minutes later … we can see 2 old jobs deleted ( near bottom )

Oldest jobs not shown. Only last 3 plus currently running ones.

Demo complete, delete …

IMPORTANT : concurrencyPolicy: Allow … Your cron jobs MUST be able to have functionality that enables more than one job to be running simultaneously. Probable file locking, startup and cleanup considerations.

3) concurrencyPolicy: Forbid

From https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#concurrency-policy

Forbid: The cron job does not allow concurrent runs; if it is time for a new job run and the previous job run hasn’t finished yet, the cron job skips the new job run.

Notice last line in YAML spec below.

This demo will see Forbid in action.

Create the Job

After a minute:

Below: one minute elapsed, original first job still running.

New job forbidden to start. ( We do not see a new job with age of around 18 seconds )

Nearly 90 seconds later — first job busy with last seconds of running.

First job complete, NOW second job starts immediately.

90 seconds later … second job completed.

Mere seconds later : third job starts.

8 seconds later … third job still busy.

kubectl describe output :

Note the original neat schedule of one new job per minute is now destroyed.

Every new job only start when previous one completes. Not on the minute, but 30 seconds later since each job runs 90 seconds.

Use concurrencyPolicy: Forbid when you want each cron job to fully complete ALL BY ITSELF, then start the next job in the schedule queue. Subsequent cron job start times depend on runtime of previous job, not on precise schedule.

kubectl get cronjob does not show any detail of all this that just happened.

Demo done, delete …

4) concurrencyPolicy: Replace

From https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#concurrency-policy

Replace : If it is time for a new job run and the previous job run hasn’t finished yet, the cron job replaces the currently running job run with a new job run

Notice last line in YAML spec below.

This demo will see Replace in action.

Previous job after 60 seconds.

New job started. Replace works. It replaced the running job that wanted to sleep for 90 seconds.

We can see in events below that after a job runs for 60 seconds it gets deleted. New one takes its place.

Second job gets same treatment: replacement after 60 seconds.

Summary in events:

Every job only runs for 60 seconds maximum. It gets replaced by new job starting every minute.

Use the logic of concurrencyPolicy: Replace when it is appropriate for your production cron job.

Original Source


Follow me to keep abreast with the latest technology news, industry insights, and developer trends.