docs: add new kubernetes build driver docs
Signed-off-by: Justin Chadwell <me@jedevc.com>pull/1208/head
							parent
							
								
									5b452b72a2
								
							
						
					
					
						commit
						900f356df9
					
				@ -0,0 +1,236 @@
 | 
			
		||||
---
 | 
			
		||||
title: "Kubernetes builder"
 | 
			
		||||
description: "Connect buildx to a kubernetes cluster"
 | 
			
		||||
keywords: build, buildx, buildkit
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
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](https://minikube.sigs.k8s.io/docs/).
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ kubectl create namespace buildkit
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then create a new buildx builder:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable)
 | 
			
		||||
if neccessary.
 | 
			
		||||
 | 
			
		||||
You should now be able to see the builder in the list of buildx builders:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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):
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).
 | 
			
		||||
    
 | 
			
		||||
For example, to create 4 replica buildkit pods:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ docker buildx create \
 | 
			
		||||
  --bootstrap \
 | 
			
		||||
  --name=kube \
 | 
			
		||||
  --driver=kubernetes \
 | 
			
		||||
  --driver-opt=namespace=buildkit,replicas=4
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Listing the pods, we get:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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](https://docs.docker.com/engine/reference/commandline/buildx_create/#kubernetes-driver-1).
 | 
			
		||||
 | 
			
		||||
## Multi-arch builds
 | 
			
		||||
 | 
			
		||||
The kubernetes buildx driver has support for creating [multi-architecture images](https://docs.docker.com/buildx/working-with-buildx/#build-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](https://www.qemu.org/) (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`:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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`:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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`:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ 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](https://github.com/moby/buildkit/blob/master/docs/rootless.md).
 | 
			
		||||
 | 
			
		||||
To enable it in your cluster, you can use the `rootless=true` driver option:
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ docker buildx create \
 | 
			
		||||
  --name=kube \
 | 
			
		||||
  --driver=kubernetes \
 | 
			
		||||
  --driver-opt=namespace=buildkit,rootless=true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This will create your pods without `securityContext.privileged`.
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue