Poor Man’s Kubernetes CD with a CronJob

Sebastien Goasguen
Bitnami Perspectives
3 min readOct 11, 2017

Continuous Integration and Deployment should be part of your software life cycle. Every time your developers write new code, a build should be triggered, all your tests should be run, then decision to deploy should be made (hopefully automatically) and your apps should be deployed.

To do this, people piece together Jenkins/Bamboo/TravisCI/CircleCI/DockerHub whatever tools that made it in their pipeline to automate building artifacts, storing them in registries, pulling them automatically etc… Just talk to my friends at Container Solutions they would love to help you with it :)

In Kubernetes, you can get started with a super simple CronJob that even though simple is super powerful. Here is the story of this CronJob.

Declarative vs Imperative

It starts with a discussion about declarative vs.imperative mindset . In an imperative mindset you tell the system how to do things. For instance you tell it to create a resource, or delete a resource, you can also tell it to scale a resource, all of this with a CLI and by passing options.

If you operate more declaratively, you need to represent the state of your infrastructure or apps in some sorts of manifests and then tell the system “go make that happen, I don’t know if it is a creation ,a deletion, a scaling action…”

In Kubernetes land, your applications will take the shape of a set of manifests. Usually a bunch of YAML. The best way to manage that YAML is to keep it under version control. Doing so, plus a declarative mindset brings you to what Weaveworks recently called GitOps.

The concept of GitOps is used at places like Google (of course…). You declare your desired state in manifests kept in Git, and you let the system reach that desired state. That’s what Kubernetes is great at. For example to launch the Guestbook example do:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/all-in-one/guestbook-all-in-one.yaml

A word about kubecfg

As a side note, generating and managing all those Kubernetes YAML manifest can be quite daunting. That’s why Bitnami invested in the ksonnet project and why we wrote kubecfg a tool that does a better job than kubectl apply

There is currently a WG that is being created to discuss how to do declarative app management in Kubernetes in a better way. Consider joining the working group and check this document from Kubernetes tech lead Brian Grant.

But back to our CronJob.

I figured, if I keep my manifest in version control, I can use a CronJob that would regularly pull my manifests from GitHub and then do a kubecfg update to deploy my app in a super declarative manner. That way I am 100% GitOps with just a CronJob and I don’t have to worry about Jenkins and what not…Super simple, yet super dope !!!

So here it is:

And here is the Cron Job:

CronJobs in Kubernetes were first proposed by Red Hater Maciej Szulik in July 2015. He just wrote a small recap of the feature for the v1.8 release.

If you are already on k8s v1.8 the apiVersion for the CronJob object will be batch/v1beta1 but I currently tested this on a v1.7.5 setup that is still on batch/v2alpha1.

The job is run every minute (of course you can tune that). It uses a gitRepo volume to download my manifests, and the image that is being used is bitnami/kubecfg:0.5.0 which contains just the latest release of kubecfg.

A few parameters are passed to be able to talk to the Kubernetes API server, like the token for the default service account used (tweak that !). And then it does an kubecfg update

Jsonnet

If you look at https://github.com/sebgoa/opencompose-jsonnet you will see that it is a fork of Antoine Legrand’s opencompose PoC. It is using jsonnet to come up with a very succint way to describe a deployment and a service.

This could be any Jsonnet based library, it does not matter. Your pick.

The end result is that when I create this cronjob, every minute it will pull my repo and deploy my app in a declarative manner. When I modify my manifests via GitHub PR, I change the desired state and I know that kubecfg and my Super duper cron job will do the rest.

Why should it be more complicated ???? let me know at Sebastien Goasguen

--

--

Sebastien Goasguen
Bitnami Perspectives

@sebgoa, Kubernetes lover, R&D enthusiast, co-Founder of TriggerMesh, O’Reilly author, sports fan, husband and father…