# Driver Kubernetes


El driver Kubernetes te permite conectar tus entornos locales de desarrollo o CI a builders en un clúster de Kubernetes, lo que facilita el acceso a recursos informáticos más potentes y, opcionalmente, en múltiples arquitecturas nativas.

## Sinopsis

Ejecuta el siguiente comando para crear un nuevo builder, llamado `kube`, que utilice el driver Kubernetes:

```console
$ docker buildx create \
  --bootstrap \
  --name=kube \
  --driver=kubernetes \
  --driver-opt=[key=value,...]
```

La siguiente tabla describe las opciones específicas del driver disponibles que puedes pasar a `--driver-opt`:

| Parámetro                                  | Tipo                     | Predeterminado                                         | Descripción                                                                                                                                                                                                                                                         |
| :----------------------------------------- | :----------------------- | :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `image`                                    | String                   |                                                        | Establece la imagen que se utilizará para ejecutar BuildKit.                                                                                                                                                                                                        |
| `namespace`                                | String                   | Espacio de nombres en el contexto actual de Kubernetes | Establece el espacio de nombres (namespace) de Kubernetes.                                                                                                                                                                                                          |
| `default-load`                             | Boolean                  | `false`                                                | Carga automáticamente las imágenes en el almacenamiento de imágenes de Docker Engine.                                                                                                                                                                               |
| `replicas`                                 | Integer                  | 1                                                      | Establece el número de réplicas de Pod a crear. Consulta [Escalabilidad de BuildKit][1].                                                                                                                                                                            |
| `requests.cpu`                             | Unidades de CPU          |                                                        | Establece el valor de solicitud de CPU en unidades de CPU de Kubernetes. Por ejemplo: `requests.cpu=100m` o `requests.cpu=2`.                                                                                                                                       |
| `requests.memory`                          | Tamaño de memoria        |                                                        | Establece la solicitud de memoria en bytes o con un sufijo válido. Por ejemplo: `requests.memory=500Mi` o `requests.memory=4G`.                                                                                                                                     |
| `requests.ephemeral-storage`               | Tamaño de almacenamiento |                                                        | Establece el valor de solicitud de almacenamiento efímero en bytes o con un sufijo válido. Por ejemplo: `requests.ephemeral-storage=2Gi`.                                                                                                                           |
| `persistent-volume-claim.requests.storage` | Tamaño de almacenamiento |                                                        | Establece el tamaño solicitado para una reclamación de volumen persistente (PVC). Cuando se configura, Buildx crea un `StatefulSet` y almacena la caché de compilación de BuildKit en la reclamación. Por ejemplo: `persistent-volume-claim.requests.storage=20Gi`. |
| `limits.cpu`                               | Unidades de CPU          |                                                        | Establece el límite de CPU en unidades de CPU de Kubernetes. Por ejemplo: `limits.cpu=100m` o `limits.cpu=2`.                                                                                                                                                       |
| `limits.memory`                            | Tamaño de memoria        |                                                        | Establece el límite de memoria en bytes o con un sufijo válido. Por ejemplo: `limits.memory=500Mi` o `limits.memory=4G`.                                                                                                                                            |
| `limits.ephemeral-storage`                 | Tamaño de almacenamiento |                                                        | Establece el límite de almacenamiento efímero en bytes o con un sufijo válido. Por ejemplo: `limits.ephemeral-storage=100M`.                                                                                                                                        |
| `buildkit-root-volume-memory`              | Tamaño de memoria        | Utiliza el sistema de archivos habitual                | Monta `/var/lib/buildkit` en un volumen respaldado por memoria `emptyDir`, con `SizeLimit` como valor. Por ejemplo: `buildkit-root-volume-memory=6G`.                                                                                                               |
| `nodeselector`                             | Cadena CSV               |                                                        | Establece las etiquetas `nodeSelector` del pod. Consulta [Asignación de nodos][2].                                                                                                                                                                                  |
| `annotations`                              | Cadena CSV               |                                                        | Establece anotaciones adicionales en el `Deployment` o `StatefulSet` y en los pods.                                                                                                                                                                                 |
| `labels`                                   | Cadena CSV               |                                                        | Establece etiquetas descriptivas (labels) adicionales en el `Deployment` o `StatefulSet` y en los pods.                                                                                                                                                             |
| `tolerations`                              | Cadena CSV               |                                                        | Configura las tolerancias a perturbaciones (tolerations) del pod. Consulta [Asignación de nodos][2].                                                                                                                                                                |
| `serviceaccount`                           | String                   |                                                        | Establece el `serviceAccountName` del pod.                                                                                                                                                                                                                          |
| `schedulername`                            | String                   |                                                        | Establece el programador responsable de programar el pod.                                                                                                                                                                                                           |
| `timeout`                                  | Tiempo                   | `120s`                                                 | Establece el límite de tiempo de espera que determina cuánto tiempo esperará Buildx a que se aprovisionen los pods antes de una compilación.                                                                                                                        |
| `rootless`                                 | Boolean                  | `false`                                                | Ejecuta el contenedor como un usuario sin privilegios root. Consulta [Modo rootless][3].                                                                                                                                                                            |
| `loadbalance`                              | String                   | `sticky`                                               | Estrategia de equilibrio de carga (`sticky` o `random`). Si se establece en `sticky`, el pod se elige mediante el hash de la ruta del contexto.                                                                                                                     |
| `qemu.install`                             | Boolean                  | `false`                                                | Instala la emulación QEMU para el soporte multi-plataforma. Consulta [QEMU][4].                                                                                                                                                                                     |
| `qemu.image`                               | String                   | `tonistiigi/binfmt:latest`                             | Establece la imagen de emulación QEMU. Consulta [QEMU][4].                                                                                                                                                                                                          |

[1]: #escalabilidad-de-buildkit
[2]: #asignacion-de-nodos
[3]: #modo-rootless
[4]: #qemu

## Escalabilidad de BuildKit

Una de las ventajas principales del driver Kubernetes es que puedes escalar el número de réplicas de los builders hacia arriba o hacia abajo para manejar una mayor carga de compilación. El escalado es configurable mediante las siguientes opciones del driver:

- `replicas=N`

  Esto escala el número de pods de BuildKit al tamaño deseado. De forma predeterminada, solo crea un único pod. Aumentar el número de réplicas te permite aprovechar múltiples nodos en tu clúster.

- `requests.cpu`, `requests.memory`, `requests.ephemeral-storage`, `limits.cpu`, `limits.memory`, `limits.ephemeral-storage`

  Estas opciones permiten solicitar y limitar los recursos disponibles para cada pod de BuildKit [de acuerdo con la documentación oficial de Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).

Por ejemplo, para crear 4 pods réplicas de BuildKit:

```console
$ docker buildx create \
  --bootstrap \
  --name=kube \
  --driver=kubernetes \
  --driver-opt=namespace=buildkit,replicas=4
```

Al listar los pods obtienes lo siguiente:

```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
```

Además, puedes utilizar la opción `loadbalance=(sticky|random)` para controlar el comportamiento del equilibrio de carga cuando hay múltiples réplicas. La opción `random` selecciona nodos aleatorios del conjunto de nodos, proporcionando una distribución uniforme del trabajo entre las réplicas. La opción `sticky` (predeterminada) intenta conectar una misma compilación realizada varias veces al mismo nodo en cada ocasión, asegurando un mejor uso de la caché local.

Para obtener más información sobre la escalabilidad, consulta las opciones de [`docker buildx create`](/reference/cli/docker/buildx/create/#driver-opt).

## Almacenamiento persistente

Establece la opción del driver `persistent-volume-claim.requests.storage` para almacenar la caché de compilación de BuildKit en una reclamación de volumen persistente (PVC) en lugar de en el sistema de archivos del pod. Cuando configuras esta opción, Buildx crea un `StatefulSet` en lugar de un `Deployment`.

Si también configuras `replicas`, cada réplica obtiene su propia reclamación de volumen persistente. Esto mantiene la caché de compilación local para cada pod a través de los reinicios.

Por ejemplo, para crear un builder con 20 GiB de almacenamiento persistente por réplica:

```console
$ docker buildx create \
  --bootstrap \
  --name=kube \
  --driver=kubernetes \
  --driver-opt=namespace=buildkit,replicas=4,persistent-volume-claim.requests.storage=20Gi
```

## Asignación de nodos

El driver Kubernetes te permite controlar la programación (scheduling) de los pods de BuildKit utilizando las opciones del driver `nodeSelector` y `tolerations`. También puedes configurar la opción `schedulername` si deseas utilizar un programador totalmente personalizado.

Puedes utilizar las opciones `annotations` y `labels` del driver para aplicar metadatos adicionales al `Deployment` o `StatefulSet` y a los pods que alojan tus builders.

El valor del parámetro `nodeSelector` es una cadena separada por comas de pares clave-valor, donde la clave es la etiqueta del nodo y el valor es el texto de la etiqueta. Por ejemplo: `"nodeselector=kubernetes.io/arch=arm64"`.

El parámetro `tolerations` es una lista de perturbaciones (taints) separada por punto y coma. Acepta los mismos valores que el manifiesto de Kubernetes. Cada entrada de `tolerations` especifica una clave de perturbación, el valor, el operador o el efecto. Por ejemplo: `"tolerations=key=foo,value=bar;key=foo2,operator=exists;key=foo3,effect=NoSchedule"`.

Estas opciones aceptan cadenas delimitadas por comas (CSV) como valores. Debido a las reglas de entrecomillado para los comandos de la shell, debes envolver los valores entre comillas simples. Incluso puedes envolver toda la opción `--driver-opt` entre comillas simples, por ejemplo:

```console
$ docker buildx create \
  --bootstrap \
  --name=kube \
  --driver=kubernetes \
  '--driver-opt="nodeselector=label1=value1,label2=value2","tolerations=key=key1,value=value1"'
```

## Compilaciones multi-plataforma

El driver Kubernetes tiene soporte para crear [imágenes multi-plataforma](/build/building/multi-platform/), ya sea utilizando QEMU o aprovechando la arquitectura nativa de los nodos.

### QEMU

Al igual que el driver `docker-container`, el driver Kubernetes también admite el uso de [QEMU](https://www.qemu.org/) (modo de usuario) para compilar imágenes para plataformas no nativas. Incluye la bandera `--platform` y especifica las plataformas a las que deseas exportar la imagen.

Por ejemplo, para compilar una imagen de Linux para `amd64` y `arm64`:

```console
$ docker buildx build \
  --builder=kube \
  --platform=linux/amd64,linux/arm64 \
  -t <user>/<image> \
  --push .
```

> [!WARNING]
>
> QEMU realiza una emulación completa de la CPU para plataformas no nativas, lo que es mucho más lento que las compilaciones nativas. Tareas pesadas como la compilación y la compresión/descompresión probablemente experimentarán un impacto significativo en el rendimiento.

El uso de una imagen de BuildKit personalizada o la invocación de binarios no nativos en las compilaciones puede requerir que actives explícitamente QEMU mediante la opción `qemu.install` al crear el builder:

```console
$ docker buildx create \
  --bootstrap \
  --name=kube \
  --driver=kubernetes \
  --driver-opt=namespace=buildkit,qemu.install=true
```

### Nativo

Si tienes acceso a nodos del clúster con diferentes arquitecturas, el driver Kubernetes puede aprovechar estos recursos para realizar compilaciones nativas. Para hacerlo, utiliza la bandera `--append` de `docker buildx create`.

Primero, crea tu builder con soporte explícito para una sola arquitectura, por ejemplo `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"
```

Esto crea un builder de Buildx llamado `kube`, que contiene un único nodo de builder llamado `builder-amd64`. Asignar un nombre al nodo mediante `--node` es opcional. Buildx generará un nombre de nodo aleatorio si no proporcionas uno.

Ten en cuenta que el concepto de nodo en Buildx no es el mismo que el concepto de nodo en Kubernetes. Un nodo de Buildx en este caso podría conectar múltiples nodos de Kubernetes de la misma arquitectura.

Con el builder `kube` ya creado, ahora puedes introducir otra arquitectura utilizando `--append`. Por ejemplo, para añadir `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"
```

Listar tus builders muestra ambos nodos para el builder `kube`:

```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*
```

Ahora puedes compilar imágenes multi-plataforma `amd64` y `arm64` especificando esas plataformas juntas en tu comando de compilación:

```console
$ docker buildx build --builder=kube --platform=linux/amd64,linux/arm64 -t <user>/<image> --push .
```

Puedes repetir el comando `buildx create --append` para tantas arquitecturas como desees admitir.

## Modo rootless

El driver Kubernetes admite el modo rootless (sin privilegios root). Para obtener más información sobre cómo funciona el modo rootless y sus requisitos, consulta la [documentación de BuildKit sin privilegios (Rootless BuildKit)](https://github.com/moby/buildkit/blob/master/docs/rootless.md).

Para activarlo en tu clúster, puedes utilizar la opción del driver `rootless=true`:

```console
$ docker buildx create \
  --name=kube \
  --driver=kubernetes \
  --driver-opt=namespace=buildkit,rootless=true
```

Esto creará tus pods sin la propiedad `securityContext.privileged`.

Requiere la versión 1.19 de Kubernetes o posterior. Se recomienda utilizar Ubuntu como kernel del host.

## Ejemplo: Crear un builder de Buildx en Kubernetes

Esta guía te muestra cómo:

- Crear un espacio de nombres (namespace) para tus recursos de Buildx
- Crear un builder de Kubernetes
- Listar los builders disponibles
- Compilar una imagen utilizando tus builders de Kubernetes

Requisitos previos:

- Tienes un clúster de Kubernetes existente. Si no tienes uno, puedes seguir la guía instalando [minikube](https://minikube.sigs.k8s.io/docs/).
- El clúster al que deseas conectarte es accesible mediante el comando `kubectl`, con la variable de entorno `KUBECONFIG` [configurada adecuadamente](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable) si es necesario.

1. Crea un espacio de nombres `buildkit`.

   Crear un espacio de nombres independiente ayuda a mantener tus recursos de Buildx aislados de otros recursos en el clúster.

   ```console
   $ kubectl create namespace buildkit
   namespace/buildkit created
   ```

2. Crea un nuevo builder con el driver Kubernetes:

   ```console
   $ docker buildx create \
     --bootstrap \
     --name=kube \
     --driver=kubernetes \
     --driver-opt=namespace=buildkit
   ```

   > [!NOTE]
   >
   > Recuerda especificar el espacio de nombres en las opciones del driver.

3. Lista los builders disponibles mediante `docker buildx ls`

   ```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
   ```

4. Inspecciona los pods en ejecución creados por el driver de compilación con `kubectl`.

   ```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
   ```

   El driver de compilación crea los recursos necesarios en tu clúster dentro del espacio de nombres especificado (en este caso, `buildkit`), mientras mantiene la configuración de tu driver localmente.

5. Utiliza tu nuevo builder incluyendo la bandera `--builder` cuando ejecutes comandos de buildx. Por ejemplo:

   ```console
   # Reemplaza <registry> con tu nombre de usuario de Docker
   # e <image> con el nombre de la imagen que deseas compilar
   docker buildx build \
     --builder=kube \
     -t <registry>/<image> \
     --push .
   ```

Eso es todo: has compilado una imagen a partir de un pod de Kubernetes utilizando Buildx.

## Lectura adicional

Para obtener más información sobre el driver Kubernetes, consulta la [referencia de buildx](/reference/cli/docker/buildx/create/#driver).

