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:
$ 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. |
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. | |
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. | |
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. |
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. |
qemu.image | String | tonistiigi/binfmt:latest | Establece la imagen de emulación QEMU. Consulta 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=NEsto 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-storageEstas opciones permiten solicitar y limitar los recursos disponibles para cada pod de BuildKit de acuerdo con la documentación oficial de Kubernetes.
Por ejemplo, para crear 4 pods réplicas de BuildKit:
$ docker buildx create \
--bootstrap \
--name=kube \
--driver=kubernetes \
--driver-opt=namespace=buildkit,replicas=4
Al listar los pods obtienes lo siguiente:
$ 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.
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:
$ 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:
$ 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, 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 (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:
$ docker buildx build \
--builder=kube \
--platform=linux/amd64,linux/arm64 \
-t <user>/<image> \
--push .
WarningQEMU 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:
$ 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:
$ 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:
$ 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:
$ 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:
$ 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).
Para activarlo en tu clúster, puedes utilizar la opción del driver rootless=true:
$ 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.
- El clúster al que deseas conectarte es accesible mediante el comando
kubectl, con la variable de entornoKUBECONFIGconfigurada adecuadamente si es necesario.
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.
$ kubectl create namespace buildkit namespace/buildkit createdCrea un nuevo builder con el driver Kubernetes:
$ docker buildx create \ --bootstrap \ --name=kube \ --driver=kubernetes \ --driver-opt=namespace=buildkitNoteRecuerda especificar el espacio de nombres en las opciones del driver.
Lista los builders disponibles mediante
docker buildx ls$ 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/386Inspecciona los pods en ejecución creados por el driver de compilación con
kubectl.$ 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 32sEl 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.Utiliza tu nuevo builder incluyendo la bandera
--buildercuando ejecutes comandos de buildx. Por ejemplo:# 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.