BreakingExpress

How to create a cron job with Kubernetes on a Raspberry Pi

One of the explanations I stood up a Kubernetes cluster on Raspberry Pis in my home was as a result of I needed to achieve financial savings by not working high-available, redundant infrastructure within the cloud. Kubernetes offers excessive availability by design. The prospects that this functionality affords are fairly superior. Need an online server to run continually? Build a container and throw it within the Kubernetes cluster. Need a service accessible on a regular basis? Package it and ship it to the Kubernetes cluster.

Legacy programs

I’ve 4 outdated Raspberry Pi packing containers doing numerous issues right here within the workplace. They do a single activity advantageous, however I’ve over-extended one of many first-generation Raspberry Pis. I’d prefer to deprecate the older Raspberry Pis as they’re now not efficient. To do this, I want to maneuver the workloads (like a cloud migration). One factor I’ve no scarcity of working on these Raspberry Pi packing containers are cron jobs. I’ve a cron for nearly the whole lot I do: Monitoring, updating internet apps, detecting adjustments in area title configurations, and many others.

k8s jobs and cron jobs

Kubernetes has the idea of jobs. To quote the official jobs documentation, “A job creates one or more pods and ensures that a specified number of them successfully terminate.” If you have got a pod that should run till completion, it doesn’t matter what, a Kubernetes job is for you. Think of a job as a batch processor.

Kubernetes cron jobs are a comparatively new factor. But I’m ecstatic that this can be a commonplace characteristic in fashionable Kubernetes clusters. It implies that I can inform the cluster one time that I need a job to run at sure instances. Since cron jobs construct on high of the prevailing job performance, I do know that the job will likely be run to completion. The job will run on one of many six nodes I’ve in my Kubernetes cluster. Even if a pod is destroyed mid-job, it would spin up on one other node and run there. High-available cron jobs have been a beast I’ve tried to slay many instances. This drawback is now solved, and all I’ve to do is implement it.

The implementation of Kubernetes cron jobs is like many different issues with Kubernetes: YAML. There are a couple of initiatives to assist with wrangling your YAML (ksonnet, for instance), however that could be a dialogue for one more article. For now, let’s put collectively a Dockerfile and a Kubernetes configuration file.

Use case

I moved my publication, DevOps’ish, off of Medium and onto Netlify with Hugo as a static web site generator. This makes for a really quick and easy-to-manage web site. But the one piece of performance misplaced within the transfer is the flexibility to schedule posts. Netlify offers a construct hook that can set off builds when known as. I can write the publication and set it to a date sooner or later. Hugo, by default, is not going to publish articles except a construct is accomplished after the desired date. Calling the construct hook URL through curl with a cron job is a approach to implement scheduled posts with Hugo on Netlify.

Dockerfile

The Dockerfile is fairly easy. Pull from alpine:newest, set up curl, and run a curlcommand. But I don’t need the construct hook URL uncovered within the Dockerfile. Loading the URL as a variable through a Kubernetes secret is advisable. Do this in order that the artifacts don’t have any delicate knowledge and they are often shared publicly. Here is the Dockerfile:

FROM alpine:newest

LABEL maintainer="Chris Short <chris@chrisshort.net>"

RUN set -x
        && apk replace
        && apk improve
        && apk add --no-cache curl

ENTRYPOINT [ "/bin/sh", "-c" ]

CMD [ "/usr/bin/curl -vvv -X POST -d '' $URL" ]

Docker construct

As my Kubernetes cluster runs on Raspberry Pi, I make sure that to tug this Dockerfile all the way down to a Raspberry Pi dev field and construct it there:

docker construct -t devopsish-netlify-cron .

The title is no matter you need it to be. I’ll probably rename this netlify-curl or another extra acceptable title after I’m prepared.

Docker registry

The subsequent step is so as to add the picture to a Docker registry. I considered working a Docker registry within the Kubernetes cluster itself, however then I noticed Google Container Registry (GCR) is a factor. Since I’ve a good quantity of stuff in Google Cloud, I made a decision to make use of GCR for simplicity and availability (additionally that complete “state inside Kubernetes” factor).

Heptio has a terrific information titled Google Cloud Registry (GCR) with external Kubernetes. If you’re going to use GCR with an exterior Kubernetes cluster, I extremely suggest studying this primary. Once GCR is configured, your Kubernetes cluster is configured to make use of GCR, and the container is constructed, it’s essential tag it for GCR:

docker tag devopsish-netlify-cron gcr.io/chrisshort-net/devopsish-netlify-cron

Then push the newly tagged container picture to GCR:

gcloud docker -- push gcr.io/chrisshort-net/devopsish-netlify-cron:newest

Kubernetes secret

As beforehand talked about, the following piece would be the Kubernetes secret. There are quite a lot of methods to pores and skin the k8s secret cat. Secrets will be loaded one time through command line or by making use of a configuration file. I selected the configuration file methodology as a result of I’ll save them in 1Password, then delete them. The secret file will look one thing like this:

apiVersion: v1
form: Secret
metadata:
  title: devopish-build-hook
sort: Opaque
knowledge:
  url: [REDACTED]

The redacted URL string would be the Netlify construct hook URL. As that is an opaque secret, the string will must be base64-encoded:

echo -n "<SECRET>" | base64

Once the bottom64 string is added to the file, apply it:

kubectl apply -f secret.yml

Cron job configuration

Piecing collectively the Kubernetes cron job configuration file is comparatively simple. ‘Schedule’ is a required subject, and should you’re accustomed to cron, it would look equivalent to the cron format string.

apiVersion: batch/v1beta1
form: CronJob
metadata:
  title: devopsish-netlify-cronjob
spec:
  schedule: "1 2-14 * * 0-1,5-6"
  jobTemplate:
    spec:
      template:
        spec:
          picturePullSecrets:
            - title: gcr-secret
          containers:
          - title: devopsish-netlify-cronjob
            picture: gcr.io/chrisshort-net/devopsish-netlify-cron:newest
            env:
              - title: URL
                valueFrom:
                  secretKeyRef:
                    title: devopish-build-hook
                    key: url
          restartPolicy: OnFailure

One pitfall I skilled is Kubernetes makes use of UTC completely. Make positive you’re taking that into consideration once you’re creating your schedule.

Here is what the Kubernetes configuration file is specifying:

  1. Create a cron job named devopsish-netlify-cronjob
  2. Schedule it to run the primary minute of each hour from 0200 to 1400 UTC on Sunday, Monday, Friday, and Saturday
  3. Pull the picture from gcr.io/chrisshort-net/devopsish-netlify-cron:newest utilizing the supplied secrets and techniques for gcr
  4. Set an setting based mostly off the URL key within the secret named devopish-build-hook
  5. Run container on cron job schedule

Apply the configuration file, and also you’re off to the races:

kubectl apply -f devopsish-netlify-cronjob.yml

Conclusion

Voilà! You have constructed a Docker container, deployed the picture to Google Container Registry, configured the Kubernetes cluster to tug photographs from GCR, created a secret to retailer the construct hook, and created the cron job. If the whole lot works okay, the next command ought to present an lively cron job:

cshort@michiganjfrog ~> kubectl get cronjob
NAME                        SCHEDULE             SUSPEND   ACTIVE    LAST SCHEDULE   AGE
devopsish-netlify-cronjob   1 2-14 * * Zero-1,5-6   False     Zero         8h              2nd

Now go rejoice your high-availability, damn-near-guaranteed-to-run-every-time Kubernetes cron job. Congratulations!

This article was initially posted on Chris Short’s blog. Reposted with permission.

Exit mobile version