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:
- Know where my source code to build lives
- Build an OCI image (using Docker or Cloud Native Buildpacks)
- Tag the image and push it to the registry of my choice (local registry for KIND, DockerHub, GCR, etc.)
- 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
apiVersion: kbld.k14s.io/v1alpha1 kind: Sources sources: - image: image-repository/image-name path: /path/to/source/code pack: build: builder: heroku/buildpacks:18
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 (
apiVersion: kbld.k14s.io/v1alpha1 kind: ImageDestinations destinations: - image: image-repository/image-name newImage: docker.io/image-repository/image-name
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
As always, refer to the kbld config documentation for the latest on what is possible.
How to Use kbld
The following examples refer to a simple Go app called mando that will be built and deployed to Kubernetes using
Building an app with kbld using a Dockerfile
If you wish to follow along, you’ll need the following:
- Install docker
- Sign up for a free DockerHub account or have access to a different image registry
- Install kbld
- Have access to a Kubernetes cluster and
kubectlif 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
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
--- apiVersion: kbld.k14s.io/v1alpha1 kind: Sources sources: - image: downey/mando path: .
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
ImageDestinations configuration tells kbld to tag and push my image to DockerHub at
Now to use this configuration, in the root of the app directory we can run:
kbld -f build -f deploy
We will then see kbld work its magic. It will:
- Build the
mandoapp using its
- Push it to DockerHub
- Update the references to the image in our Kubernetes
Deploymentto use the digest for the image we just built
- 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 -
It might not seem like much at first. But after dozens of cycles of
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
--- apiVersion: kbld.k14s.io/v1alpha1 kind: Sources sources: - image: downey/mando path: . pack: build: builder: cloudfoundry/cnb:tiny
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 -
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.
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! 🌝