Post

Meet Renovate - Your Update Automation Bot for Kubernetes and More!

Keeping track of container image updates is hard. I started using Renovate Bot to to track these for me and I now get pull requests from a bot for my Docker and Kubernetes container images. It’s a game changer.

A HUGE thanks to Datree for sponsoring this video!

Secure Your Kubernetes, Prevent Misconfigurations

https://www.datree.io

📺 Watch Video

Why use Renovate?

How much time do you spend looking for updated container images for services you have running in your Kubernetes cluster? 5 minutes, 5 hours? Never? I used to spend hours a week checking for new container images, reading up on the changes, and not really knowing if it was going to break my cluster or not. It was super tedious doing this to the point where I almost stopped doing it. That’s when I discovered Renovate Bot. Renovate is a dependency update automation tool that scans your software, discovers dependencies, and checks to see if an update exists, and if there is one, it will automatically help you out by submitting a pull request on your code base. It works out of the box and supports a wide variety of languages and technologies, it’s highly configurable putting you in control of what gets updated and when, and it’s pretty smart too and can automatically detect dependencies and suggest ideas for improvement.

Here’s the cool thing about it too, not only can it scan for all sorts of dependencies, it also gives you your choice of how you want to run it. Want to run it locally as a node module or from a CLI? Or in a Docker container? Or ever self host it in your Kubernetes cluster? No problem! Want to scan dependencies in GitHub, GitLab, AWS CodeCommit or other Git providers? No problem at all. One of the great things about Renovate is that because it’s open source, it puts you in control of how you want to run it, where you want to run it, and when you want to run it. So today we’ll be setting up Renovate bot to give us a helping hand with our Kubernetes resources. We’ll create a GitHub repo to house our Kubernetes deployments, add the Renovate bot to our repo, and then let it help us out by opening pull requests when it sees updates to any of the container images we’re using. Yeah… I feel like I just hired a devops engineer for free.

Renovate works with many different source control providers like GitHub, GitLab, CodeCommit, and many others. You also have your choice of how you want to manage Renovate, meaning you can self-host it with Docker or Kubernetes, or run it as a GitHub app for free that’s hosted by Renovate’s parent company Mend.

Create GitHub Repo

We’re going to go with GitHub and the GitHub app because it’s super simple to set up. First we need to create a github repo, this is as simple as going to GitHub and well, creating a new repo. After naming your repo you’ll want to choose whether to make this public or private. The choice is up to you and Renovate will work either way.

Note: if you want to see the repo I created in this post and video, you can check it out here technotim-k8s-renovate

GitHub Repo! Create a repo in GitHub

After creating the repo you’ll want to clone it to your machine. Now, I know that it’s empty, but we’ll be adding some things here shortly. After cloning it, I am going to open it up with a VSCode but any editor will do.

Now that our repo is cloned, we’re going to add some Kubernetes resources so that Renovate can start analyzing our resources for updates. We’re going to create a simple nginx deployment and service.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.24-alpine
          ports:
            - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

For this deployment we’re going to use an older nginx container image tag because we want to see the Renovate bot actually work, so we’ll go out to Docker Hub and choose an older tag. We’ll then put that image tag in our deployment. Now that we have this manifest, let’s commit this code and push it up.

Add Renovate Bot

Now that we have a simple Kubernetes deployment committed to our repo, we should add the Renovate bot to start analyzing our code. We can do this by going out to GitHub, finding the Renovate app, and installing it in our repo. You need to authorize this app for your repo or org. Once you authorize this app and choose which repos it has access to you are all set!

If you ever decide to change your mind and remove this app for your repo, you can go to the repo settings and remove this app at any time.

Once the Renovate bot is authorized and installed, it won’t actually do anything until you merge a Pull Request that will be opened by the bot on your repo! This pull request is a special “onboarding” pull request that will show you what the bot has detected along with adding a default config for the bot. Renovate won’t take any further actions until you accept and merge this pull request. Once you have reviewed this PR, you can merge it in and it will activate the bot on your repo.

Renovate in GitHub Marketplace! Add the Renovate app to your repo

Our First (Real) Pull Request

After merging the onboarding PR, we can go and take a look at the logs for the bot on Mend’s bot page. Here we can see that it is trying to auto detect all of the various dependencies that the bot supports. It’s checking for ansible, docker-compose, flux, gradle, helm, and many other dependencies. But it doesn’t know how to handle Kubernetes files out of the box because Kubernetes files don’t really have a naming convention because there really isn’t one. So we’ll need to tell Renovate how to check for Kubernetes files in our config.

Renovate logs! Here you can see Renovate trying to scan our repo and automatically detect dependencies

So we’ll need to git pull to get latest and we should see our Renovate config file. We’ll need to add the file match for Kubernetes files. You’ll want to be sure that you use the right extension here, whether that be yml or yaml, both are acceptable but I typically use yml so that’s what I am going to use here.

1
2
3
4
5
6
7
8
9
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:base"
  ],
  "kubernetes": {
    "fileMatch": ["\\.yml$"]
  }
}

Once we’ve made that change to our config locally, we’ll then commit that change and push it up.

Once we push this change up and it scans our repo, we can see a new issue that was created! This is a special type of issue that Renovate creates for us and it is kind of like a dashboard for all of our dependencies.

If we look at this issue, it’s telling us that it detected a new dependency that’s related to Kubernetes and that it detected not only our nginx tag but also our Kubernetes API version for the deployment. Super awesome. If you like you can choose to disable this dashboard issue in your config, but I would recommend keeping it.

If we look at the logs again from Renovate, we can also see that it detected our nginx deployment and that it created a PR for us to review. Now for the actual PR. We should see a new PR that was opened from the Renovate bot!

If we look at this PR we can see the proposed changes, it’s suggesting that we change our nginx container image from 1.24 to 1.25 which is the current latest tag. If we’re happy with the change we can merge it into our code with just a click.

How to Handle “latest” tag

Now our code base is up to date with the latest container image. What happens if a container you are using only has one tag, say like the “latest” tag? Well, let’s find out.

Let’s say for instance we’re running Wordpress in our cluster, and we create a deployment.yml and in our deployment.yml we specify the “latest” tag vs. a versioned tag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - name: wordpress
          image: wordpress:latest
          ports:
            - containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  selector:
    app: wordpress
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

After we commit and push this up, we can wait for Renovate to check our repository again for new dependencies, or we can manually trigger one by going back to the dependency dashboard issue and check this box to trigger it to run again.

Now, if we look at the logs again we should see that it detected Wordpress, however it is unversioned. The latest tag is nondeterministic, meaning that it is not deterministic, or simply put, it can mean more than one thing. Renovate can’t use this because it can’t determine what the current version is and what the next possible version is. So, instead of pinning this version to “latest”, we can actually pin it to a digest.

So if we look at the current latest tag in Docker Hub and inspect the digest, we can see it here.

It’s this long string of characters:

DIGEST:sha256:75ba772cce073ec2aa6cec95c5ca229dfde9029c49874350a971499d567adae7

The digest is an immutable identifier for a container image and it is deterministic, meaning it can’t be changed and it only references one image. We can use that for Renovate. Once we have that, we can then pin our Wordpress container to this digest by using the like this, it’s:

container image @ sha256 : digest

Now if we make this change, commit this and push it up, we are now pinned to the digest which is also the same as “latest”. Again, if we want to force a scan instead of waiting, we can go back to this Dashboard issue, check the check box and then go look at the logs. We can now see that it detected our Wordpress container image along with the digest and it can now compare this to the current digest and open a PR if it needs to. If we take a look at the issue Dependency dashboard, we can now see that it detected Wordpress pinned to the digest. We won’t see a PR now because this digest is the latest digest, however if Wordpress releases a new container image with a new digest we will get a pull request to replace the digest. Awesome, so that solves the “latest” problem.

Working with Helm Charts

So that’s awesome, we have ways to work with Kubernetes manifests whether they are pinned to a versioned tag or an unversioned tag, but what about helm charts? Well, helm charts are just as easy. Let’s say we wanted to source control our mysql helm deployment, all we have to do is create a our helm values file and include the version as well as the repository.

1
2
3
4
5
6
7
8
9
10
11
12
---
image:
  repository: bitnamicharts/mysql
  version: 9.9.0
persistence:
  enabled: true
  size: 10Gi
architecture: replication
auth:
  existingSecret: mysql-secret
primary:
  replicaCount: 1

If you don’t specify the repository it will default to Docker hub, but as you can see here I am getting this chart from Bitnami. After we commit and push this up, we should now see a new dependency type of helm and since it detected an update we should also see a pull request to update this file!

Renovate helm charts! updating helm charts with Renovate are just as easy!

Wrapping Up

So now with Renovate bot we can keep track and upgrade our Kubernetes deployment and even helm charts but I bet you are wondering how you can deploy them? There are quite a few ways to deploy these resources using GitOps tools like Flux and ArgoCD, or even just a simple CI task that runs kubectl and or helm. I have a few videos on this topic. What about Docker deployments? Well if you’re interested in how to automate deployments with Docker and Renovate let me know in the comments below.

Well, I learned a ton about Renovate Bot, how to add it to your Git Repository and how to automate Pull Requests when there are updates available, and I hope you leanred something too! And remember if you found anything in this post helpful, don’t forget to share. Thanks for Reading!

Join the conversation

⚙️ See all the hardware I recommend at https://l.technotim.live/gear

🚀 Don’t forget to check out the 🚀Launchpad repo with all of the quick start source files

This post is licensed under CC BY 4.0 by the author.