8.5 KiB
Kubernetes driver
The buildx kubernetes driver allows connecting your local development or ci environments to your kubernetes cluster to allow access to more powerful and varied compute resources.
This guide assumes you already have an existing kubernetes cluster - if you don't already have one, you can easily follow along by installing minikube.
Before connecting buildx to your cluster, you may want to create a dedicated
namespace using kubectl
to keep your buildx-managed resources separate. You
can call your namespace anything you want, or use the existing default
namespace, but we'll create a buildkit
namespace for now:
$ kubectl create namespace buildkit
Then create a new buildx builder:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit
This assumes that the kubernetes cluster you want to connect to is currently
accessible via the kubectl command, with the KUBECONFIG
environment variable
set appropriately
if neccessary.
You should now be able to see the builder in the list of buildx builders:
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
kube kubernetes
kube0-6977cdcb75-k9h9m running linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
default * docker
default default running linux/amd64, linux/386
The buildx driver creates the neccessary resources on your cluster in the
specified namespace (in this case, buildkit
), while keeping your
driver configuration locally. You can see the running pods with:
$ kubectl -n buildkit get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kube0 1/1 1 1 32s
$ kubectl -n buildkit get pods
NAME READY STATUS RESTARTS AGE
kube0-6977cdcb75-k9h9m 1/1 Running 0 32s
You can use your new builder by including the --builder
flag when running
buildx commands. For example (replacing <user>
and <image>
with your Docker
Hub username and desired image output respectively):
$ docker buildx build . \
--builder=kube \
-t <user>/<image> \
--push
Scaling Buildkit
One of the main advantages of the kubernetes builder is that you can easily scale your builder up and down to handle increased build load. These controls are exposed via the following options:
replicas=N
- This scales the number of buildkit pods to the desired size. By default, only a single pod will be created, but increasing this allows taking of advantage of multiple nodes in your cluster.
requests.cpu
,requests.memory
,limits.cpu
,limits.memory
- These options allow requesting and limiting the resources available to each buildkit pod according to the official kubernetes documentation here.
For example, to create 4 replica buildkit pods:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,replicas=4
Listing the pods, we get:
$ kubectl -n buildkit get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kube0 4/4 4 4 8s
$ kubectl -n buildkit get pods
NAME READY STATUS RESTARTS AGE
kube0-6977cdcb75-48ld2 1/1 Running 0 8s
kube0-6977cdcb75-rkc6b 1/1 Running 0 8s
kube0-6977cdcb75-vb4ks 1/1 Running 0 8s
kube0-6977cdcb75-z4fzs 1/1 Running 0 8s
Additionally, you can use the loadbalance=(sticky|random)
option to control
the load-balancing behavior when there are multiple replicas. While random
should selects random nodes from the available pool, which should provide
better balancing across all replicas, sticky
(the default) attempts to
connect the same build performed multiple times to the same node each time,
ensuring better local cache utilization.
For more information on scalability, see the options for buildx create.
Multi-platform builds
The kubernetes buildx driver has support for creating multi-platform images, for easily building for multiple platforms at once.
QEMU
Like the other containerized driver docker-container
, the kubernetes driver
also supports using QEMU (user mode) to build
non-native platforms. If using a default setup like above, no extra setup
should be needed, you should just be able to start building for other
architectures, by including the --platform
flag.
For example, to build a Linux image for amd64
and arm64
:
$ docker buildx build . \
--builder=kube \
--platform=linux/amd64,linux/arm64 \
-t <user>/<image> \
--push
Warning QEMU performs full-system emulation of non-native platforms, which is much slower than native builds. Compute-heavy tasks like compilation and compression/decompression will likely take a large performance hit.
Note, if you're using a custom buildkit image using the image=<image>
driver
option, or invoking non-native binaries from within your build, you may need to
explicitly enable QEMU using the qemu.install
option during driver creation:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,qemu.install=true
Native
If you have access to cluster nodes of different architectures, we can
configure the kubernetes driver to take advantage of these for native builds.
To do this, we need to use the --append
feature of docker buildx create
.
To start, we can create our builder with explicit support for a single
architecture, amd64
:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--platform=linux/amd64 \
--node=builder-amd64 \
--driver-opt=namespace=buildkit,nodeselector="kubernetes.io/arch=amd64"
This creates a buildx builder kube
containing a single builder node builder-amd64
.
Note that the buildx concept of a node is not the same as the kubernetes
concept of a node - the buildx node in this case could connect multiple
kubernetes nodes of the same architecture together.
With our kube
driver created, we can now introduce another architecture into
the mix, for example, like before we can use arm64
:
$ docker buildx create \
--append \
--bootstrap \
--name=kube \
--driver=kubernetes \
--platform=linux/arm64 \
--node=builder-arm64 \
--driver-opt=namespace=buildkit,nodeselector="kubernetes.io/arch=arm64"
If you list builders now, you should be able to see both nodes present:
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
kube kubernetes
builder-amd64 kubernetes:///kube?deployment=builder-amd64&kubeconfig= running linux/amd64*, linux/amd64/v2, linux/amd64/v3, linux/386
builder-arm64 kubernetes:///kube?deployment=builder-arm64&kubeconfig= running linux/arm64*
You should now be able to build multi-arch images with amd64
and arm64
combined, by specifying those platforms together in your buildx command:
$ docker buildx build --builder=kube --platform=linux/amd64,linux/arm64 -t <user>/<image> --push .
You can repeat the buildx create --append
command for as many different
architectures that you want to support.
Rootless mode
The kubernetes driver supports rootless mode. For more information on how rootless mode works, and it's requirements, see here.
To enable it in your cluster, you can use the rootless=true
driver option:
$ docker buildx create \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,rootless=true
This will create your pods without securityContext.privileged
.
Further reading
For more information on the kubernetes driver, see the buildx reference.