Setting up “push to deploy” Kubernetes workflow with Github and Keel

Karolis Rusenas
ITNEXT
Published in
6 min readJul 26, 2018

--

In this tutorial, we will configure several tools to enable automated Kubernetes updates on Git push. This workflow is mostly useful when developing apps for Kubernetes. For production, I would recommend tag approach where a tagged release would trigger an image build and Keel update policies would increase the version.

Once a workflow is ready, any push to the master branch (or merge requests from develop/feature branches) will update your app running in Kubernetes.

In this tutorial we will use:

  • Minikube — our local development Kubernetes environment. Mac users are free to use Docker for Mac with Kubernetes support, works fine!
  • GitHub — we will store our code here
  • DockerHub — our Docker images will be built and stored here
  • Webhook Relay — will relay public webhooks to our internal Kubernetes environment so we don’t have to expose Keel to the public internet

TL;DR

  1. Push to GitHub starts auto build in DockerHub
  2. When DockerHub finishes building, sends a webhook through Webhook Relay to Keel
  3. Keel finds any affected workloads that use that image and update them.

Pros:

  • Easy to set up, even though this guide seems long, it’s just a lot of screenshots and code snippets for a dummy app.
  • No lock-ins into any cloud provider tools (I use Google Cloud builder instead of DockerHub auto builds as it’s faster)
  • Lightweight infrastructure — no need to run things like Spinnaker that would reduce your wallet to ashes, Keel uses maybe 12–20MB of RAM and pretty much no CPU.
  • Once set up, will serve you for years. I have been using this setup for more than a year and did ~250 releases through it, never lets you down.

Set up GitHub repository

First, let’s set up our versioning control system. Let’s create a local repo of our example app and push it to our GitHub repository.

Our example app will be a really really simple one:

Commit your code and push to remote:

Configure Webhook Relay forwarding

In this step we will configure Webhook Relay to forward DockerHub webhooks our internal Kubernetes environment. This is especially useful when developing on a local Kubernetes cluster as receiving webhooks from public services can be slightly more complicated.

Let’s prepare configuration:

$ relay forward -b dockerhub — no-agent http://localhost:9300
Forwarding configuration created:
https://my.webhookrelay.com/v1/webhooks/b968afa1-b737-4385-bc0f-473dbc2007b4 -> http://localhost:9300
In order to start receiving webhooks — start an agent: ‘relay forward’

We will need that long URL for our next step when configuring DockerHub webhooks.

Configure DockerHub (code repository + webhook)

Now, we need to tell DockerHub to build a new image on every GitHub push to the master branch. First, go to https://cloud.docker.com, then Repositories and click on Create button. Once you have created the repository, link it to your GitHub account and click on Configure Automated Builds:

Select your GitHub repository and create a trigger that will:

  • React to changes on a master branch
  • Tag image as latest

Ensure that autobuild is switched on and click on “Save and Build”. You will get your first image prepared.

Also, we will need to setup DockerHub webhooks to Keel via Webhook Relay. For some reason, that configuration is not available on https://cloud.docker.com and we have to go to https://hub.docker.com:

Deploy Keel and your app

First, we need to deploy Keel with Webhook Relay sidecar. This is a one-off thing after which when you add more applications to your Kubernetes environment you don’t need to repeat this step.

Webhook Relay daemon will need authentication details to connect. We can use relay CLI to configure and insert secret into our Kubernetes environment:

kubectl create namespace keel

Now, let’s create a secret:

relay ingress secret --name webhookrelay-credentials --namespace keel

Deploying Keel

now, if your cluster has RBAC enabled, use this template (if you are using Minikube then by default it should be enabled):

kubectl create -f https://raw.githubusercontent.com/keel-hq/keel/master/deployment/deployment-rbac-whr-sidecar.yaml

and if there’s no RBAC in your cluster, use:

kubectl create -f https://raw.githubusercontent.com/keel-hq/keel/master/deployment/deployment-norbac-whr-sidecar.yaml

TIP: Feel free to save deployment manifest locally and add things like Slack or other chat provider notifications, approvals and so on. For the sake of simplicity we are omitting those steps in this tutorial.

So, when we create it Kubernetes should complain a bit about already existing namespace but that’s expected:

$ kubectl create -f https://raw.githubusercontent.com/keel-hq/keel/master/deployment/deployment-rbac-whr-sidecar.yaml
serviceaccount “keel” created
clusterrolebinding.rbac.authorization.k8s.io “keel-clusterrole-binding” created
clusterrole.rbac.authorization.k8s.io “keel-clusterrole” created
deployment.extensions “keel” created
Error from server (AlreadyExists): error when creating “https://raw.githubusercontent.com/keel-hq/keel/master/deployment/deployment-rbac-whr-sidecar.yaml": namespaces “keel” already exists
$ kubectl get pods -n keel
NAME READY STATUS RESTARTS AGE
keel-f8b5959cc-jrgcd 2/2 Running 0 8s

Deploy your app

Now, we need to create a deployment file of our app:

Save it as deployment.yaml and create it via kubectl:

kubectl create -f deployment.yaml

Check whether it’s running:

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pushwf-8476855f97-nw4st 1/1 Running 0 1m
$ kubectl logs pushwf-8476855f97-nw4st
App is starting, version: v0

Now, update your Go program’s version string to v1:

Commit and push. In a minute or two (depending on how fast DockerHub can build your image) our app should be updated. Since it’s using webhooks, an update should be pretty much instantaneous.

If you visit Webhook Relay dockerhub bucket’s page, it should show relayed webhook:

Let’s check our deployments rollout history:

$ kubectl rollout history deployment/pushwf
deployments “pushwf”
REVISION CHANGE-CAUSE
1 <none>
2 keel automated update, version latest -> latest

And logs, just to be sure that our application is running the latest code:

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pushwf-74c574f9cf-l6lq2 1/1 Running 0 4m
$ kubectl logs pushwf-74c574f9cf-l6lq2
App is starting, version: v1

Conclusion

While setting up Keel and Webhook Relay can take several of your precious minutes away, it saves an enormous amount of time later. Not only you get an instant update to your applications based on policies but you also ensure that you won’t update wrong cluster or environment by mistake. And, of course, you won’t even need to use kubectl for your application updates.

Once Keel is set up in your cluster in can manage many (all) of your applications. When you add your next app to the cluster, just specify the policy and point DockerHub webhook to the same Webhook Relay endpoint. Keel will filter out relevant deployments based on webhook payload and update them.

If you have any questions or find parts of this tutorial incorrect, please raise an issue on Keel’s repository here

Originally published at keel.sh.

--

--

Founder of webhookrelay.com, keel.sh, helping companies build their products. Expert in Kubernetes, Docker, storage systems and networks