How to Create a Kubernetes Cronjob

Kubernetes CronJob

Containers excel at running short lived jobs and Kubernetes just so happens to have a built in scheduler. It’s the perfect combo! But you probably already know this – that’s why you’re here. So strap in get ready to create your first Kubernetes CronJob, bookmark this page, share it, add it to your team’s docs, or just enjoy reading it.

The steps in the ‘Step by Step Guide‘ section below will guide you through creating a Kubernetes cronjob. Before proceeding it’s wise to ensure you have the prerequisites that allow you to follow along and if you’d like to get a little more information about why Kubernetes is such a great cron job scheduler you can take a gander at the ‘Why Kubernetes Cronjobs‘ section.

Why Kubernetes Cronjobs

  1. The first reason why Kubernetes cronjobs are fantastic are that they run on their own individual containers allowing you to run the EXACT container you want. This allows you to lock each cron job to a certain version, upgrade the crons individually for a gradual less risky upgrade, and customize each container with the dependencies that they need.
  2. Second, you get to choose how many resources the cron job receives. During the creation of a cron job you can set the minimum amount of resources needed to run the job ensuring that it gets run on a Kuberenetes node that has enough resources to complete the job. You also get to set the resource limitations for the job to make sure it doesn’t overwhelm the server.
  3. Third, Kubernetes cronjobs have built in retry policies. If you cron job fails should you try to re-run it? How many times should you try to re-run it? This is a feature I very much wanted back when I ran ‘cron’ servers.
  4. Fourth, you automatically inherit all of the Kubernetes monitoring features. If you have Loki setup, your job’s logs will be sent there without additional configuration and the same applies to Prometheus!

Prerequisites

  • An active Minikube instance or Kubernetes cluster.

Step by Step Guide: Create a Kubernetes CronJob

1.) As with nearly everything in Kubernetes, let’s start by creating a yaml file! We’ll name it cron.yaml and go into the details of what each line is doing underneath the file.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: meow-cron
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: meow-cron
            image: alpine:latest
            imagePullPolicy: IfNotPresent
            args:
            - /bin/sh
            - -c
            - echo "Meow Meow"
          restartPolicy: OnFailure
      backoffLimit: 6
  • apiVersion: This is where we specify which Kubernetes API Version to use. At the time of writing the current version is batch/v1beta1.
  • kind: What kind of resource do we want from Kubernetes? A CronJob of course!
  • metadata: Specifies some information to help us understand what this Kubernetes CronJob is. In this case, we say that it’s name is meow-cron, which is at least a mildly creative name if you ask me.
  • spec: Now we get to the good stuff. The spec section allows us to configure our Kubernetes CronJob the way we like.
    • Schedule: Tells the cron job when to run in traditional cron scheduler fashion. If you don’t know how to format cron job scheduling I’d recommend hoping over to this cron job generator website. Note that it uses the timezone configured on your kube-controller-manager.
    • jobTemplate: We have the schedule set, this next section allows you to specify what it will do.
      • spec.template.spec: let’s just jump down a few sections here to configure the template.
        • containers: You’ll notice this is a list of containers. This example just runs one.
          • name: The name of your job
          • image: The image that will be used to run your Kubernetes CronJob. In this example we’re just using alpine because we don’t need anything special, but you will probably want this to be set to the image that contains your code or script you need to run.
          • imagePullPolicy: Should it pull the new image? If you’re using the ‘latest’ tag for your own image you’ll want this set to ‘Always‘ so that it’s not content using the image it already has on the Kubernetes node.
          • args: This is the pirate section (Arg!). Just kidding, this is where you will specify what command you want the container to run. You’ll notice it has the awkward ‘/bin/sh -c’ thing going on before the command. This is just to make sure that it encapsulates the entirety of the commands that come after. Does the ‘meow-cron’ name make sense now? You know, cause it Meows…
          • restartPolicy: What should Kubernetes do when the cronjob fails? This can be set to ‘OnFailure‘ meaning – restart if it fails or ‘Never‘ indicating it shouldn’t try to re-run.
      • backoffLimit: How many times should the pod retry the failed job? If this isn’t set it will default to 6.

2.) That was a lengthy section! This next step is an easy one. Let’s apply that Kubernetes CronJob!

$ kubectl apply -f cron.yaml 
cronjob.batch/meow-cron created

3.) It looks like the Kubernetes cronJob was properly installed. Let’s verify though.

$ kubectl get cronjob
NAME        SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
meow-cron   */1 * * * *   False     0        41s             60s

4.) Excellent the cron is installed! If we wait at least a minute we should see that the job has run as pod as well.

$ kubectl get pods
NAME                         READY   STATUS      RESTARTS   AGE
meow-cron-1609532760-m5tjf   0/1     Completed   0          2m57s
meow-cron-1609532820-7chtb   0/1     Completed   0          117s
meow-cron-1609532880-4xfcb   0/1     Completed   0          56s

5.) The status is ‘Completed’ indicating it didn’t error out, but let’s see the logs for one of those pod.

$ kubectl logs meow-cron-1609532880-4xfcb
Meow Meow

Hey! It’s echo’d Meow Meow just like we wanted!

6.) This probably isn’t the most useful cron to have installed, so let’s end this journey by uninstalling our cron.

$ kubectl delete cronjob meow-cron
cronjob.batch "meow-cron" deleted

Conclusion

Hopefully you followed along, learned how to install a Kubernetes CronJob, and are feeling confident moving your cron jobs to Kubernetes. Now that you have a cron, I’d recommend playing around with it. Try changing the backoff limit or restart policy, or intentionally having your job spit out an error to get more familiar with the messages that you might see down the road.

If you liked this guide make sure it’s easy to find for you and your teammates next time by bookmarking it, sharing it, or adding it to your team’s docs.

1 thought on “How to Create a Kubernetes Cronjob”

  1. Pingback: Kubernetes Debug Init Containers - Swiss Army DevOps

Leave a Reply

Your email address will not be published. Required fields are marked *