How to use kbld to Rapidly Iterate on Kubernetes Deployed Apps

downey

Tim Downey

Posted on May 28, 2020

How to use kbld to Rapidly Iterate on Kubernetes Deployed Apps

Obligatory shipping container cover image by Boba Jovanovic on Unsplash

What is kbld?

When creating applications that extend or interact with Kubernetes, there are times when it's necessary to deploy and develop against a real K8s cluster. While Kubernetes makes it trivial to apply and roll out new changes, the building and pushing new dev Docker images for your application can be a rigamarole. On top of that, you also have to remember to configure the imagePullPolicy for your containers to Always. Otherwise, who knows if the node your app ends up running on has the old image cached!

Fortunately, there is a tool that can help solve all of these problems. The kbld CLI (pronounced "k build") assists with all things around image building and pushing for Kubernetes. It's under active development so refer to the kbld site for the most up to date feature set, but I'm a fan of its ability to do the following:

  1. Know where my source code to build lives
  2. Build an OCI image (using Docker or Cloud Native Buildpacks)
  3. Tag the image and push it to the registry of my choice (local registry for KIND, DockerHub, GCR, etc.)
  4. Find references to the image in Kubernetes deployment YAMLs and replace vague references with image digests for deterministic deployments

I'm less of a fan, however, of its terse documentation. So in this post, I'm going to show how I use kbld to build Docker images for my projects.

Understanding kbld Configuration

Like most things in the Kubernetes ecosystem, the kbld CLI is configured by YAML files. There are several options here, but the two main YAML objects I use are Sources and ImageDestinations.

Sources

apiVersion: kbld.k14s.io/v1alpha1
kind: Sources
sources:
- image: image-repository/image-name
  path: /path/to/source/code
  pack:
    build:
      builder: heroku/buildpacks:18
Enter fullscreen mode Exit fullscreen mode

A Sources object declares the images that kbld should be responsible for building. It includes information about the path for the source code of an image as well as configuration for the image builder (docker or pack).

ImageDestinations

apiVersion: kbld.k14s.io/v1alpha1
kind: ImageDestinations
destinations:
- image: image-repository/image-name
  newImage: docker.io/image-repository/image-name
Enter fullscreen mode Exit fullscreen mode

ImageDestinations tell kbld how it should tag and push the images that it has built. It's a pretty simple resource, and I was surprised at first that there was nothing about authentication here for private registries. That config, however, comes in either through your Docker config or as environment variables. See these kbld authentication docs for more information on that.

Are these Kubernetes Resources?

An astute developer might recognize that these kbld resources look suspiciously similar to Kubernetes resource objects and wonder if there are any CRDs involved here. That's not the case, though. The similarities are purely superficial, and these resources are used client-side directly by the kbld CLI.

As always, refer to the kbld config documentation for the latest on what is possible.

How to Use kbld

GitHub logo tcdowney / mando

this is the way

Docker Image Size (latest by date) Docker Image Version (latest by date)

mando

this is the way

just a little app for testing path-based routing

docker run -p 8080:8080 downey/mando

build and deploy

can be built and deployed to Kubernetes with kbld

kbld -f build -f deploy | kubectl apply -f -
Enter fullscreen mode Exit fullscreen mode

The following examples refer to a simple Go app called mando that will be built and deployed to Kubernetes using kbld.

Building an app with kbld using a Dockerfile

If you wish to follow along, you'll need the following:

  1. Install docker
  2. Sign up for a free DockerHub account or have access to a different image registry
  3. Install kbld
  4. Have access to a Kubernetes cluster and kubectl if you want to deploy

To start, since we'll be publishing to an OCI image registry, we'll first need to authenticate. Since I'm pushing my images to DockerHub that means I just need to docker login.

For the following, I'll be working off of the kbld-dockerfile-example branch of my test app repo.

In this repo, I have an example Deployment for Kubernetes in the deploy directory and the kbld files within the build directory.

---
apiVersion: kbld.k14s.io/v1alpha1
kind: Sources
sources:
- image: downey/mando
  path: .
Enter fullscreen mode Exit fullscreen mode

Here I've configured kbld to build my image, downey/mando, using the code and Dockerfile at the root of my repository.

---
apiVersion: kbld.k14s.io/v1alpha1
kind: ImageDestinations
destinations:
- image: downey/mando
  newImage: docker.io/downey/mando
Enter fullscreen mode Exit fullscreen mode

This ImageDestinations configuration tells kbld to tag and push my image to DockerHub at docker.io/downey/mando.

Now to use this configuration, in the root of the app directory we can run:

kbld -f build -f deploy
Enter fullscreen mode Exit fullscreen mode

We will then see kbld work its magic. It will:

  1. Build the mando app using its Dockerfile
  2. Push it to DockerHub
  3. Update the references to the image in our Kubernetes Deployment to use the digest for the image we just built
  4. Output the Kubernetes YAML with all changes

We can then either write this output to a file or deploy it directly to Kubernetes:

kbld -f build -f deploy | kubectl apply -f -
Enter fullscreen mode Exit fullscreen mode

It might not seem like much at first. But after dozens of cycles of docker build, docker push, updating Kubernetes config to point to a new tag, and deploying, kbld can end up saving a bunch of time!

Where I really find kbld useful though, is with Cloud Native Buildpacks.

Building an app with kbld using Buildpacks

For this section I'll be working off of the kbld-pack-example branch of my test app repo. If you're unfamiliar with the concept of buildpacks, I'd encourage you to learn more about them or check out my blog post on deploying apps to Kubernetes with Buildpacks.

Using Buildpacks instead of a Dockerfile to build is simple with kbld. The flow is pretty much the same -- instead of a Dockerfile, we will use the pack CLI (install it if you haven't already) and make some minor tweaks to our Sources YAML.

---
apiVersion: kbld.k14s.io/v1alpha1
kind: Sources
sources:
- image: downey/mando
  path: .
  pack:
    build:
      builder: cloudfoundry/cnb:tiny
Enter fullscreen mode Exit fullscreen mode

Here we tell kbld which "builder" to use. I'm using the cnb:tiny builder since it's optimized for creating "distroless" lightweight images for Go binaries. Perfect for this use case. If you're unsure which builder to use, you can always run pack suggest-builders to get an up-to-date list of builders from Cloud Foundry and Heroku.

Anyways, as I said earlier, the flow is the same as before. To build and deploy, just run:

kbld -f build -f deploy | kubectl apply -f -
Enter fullscreen mode Exit fullscreen mode

The kbld CLI will now build using pack instead of docker! Since I use the pack CLI pretty infrequently, I'm more than happy to hand over the reigns to kbld and let it orchestrate the build and push.

Summary

Well that's about it. If you've gotten this far, hopefully this post has helped demystify some of the basic use cases for kbld and how it can help streamline the Docker image push-build-deploy flow. If you're looking to learn more, check out the kbld docs or join the #k14s channel on Kubernetes Slack. Good luck! 🌝

💖 💪 🙅 🚩
downey
Tim Downey

Posted on May 28, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related