Crear un clúster de Kubernetes para desarrollo con Kind

Hace más de dos años, cuando empecé a trabajar con Kubernetes, compartí contigo algunas opciones para tener un clúster con el que poder desarrollar tus aplicaciones en local. Hoy quiero ampliar esa lista con una herramienta llamada kind que te permite generar clústers sobre Docker, incluso multi-nodo y/o simulando alta disponibilidad.

Instalación

Para poder usar kind lo primero que necesitas es un host con Docker. Por otro lado, debes instalar la herramienta kind en tu sistema operativo. En el caso de MacOs, como muchas otras herramientas, se puede conseguir a través de Homebrew:

brew install kind

Ahora ya tienes todo lo que necesitas para montar tu clúster con esta herramienta.

Crear un clúster de Kubernetes con kind

El comando que debes usar para crear uno, con las opciones por defecto, es el siguiente:

kind create cluster

Esto generará esta salida:

kind create cluster

Lo que ha hecho kind es, por un lado, ha creado un contenedor llamado kind-control-plane, que es el que va a simular tu clúster. Este tiene además el puerto 6443 expuesto para poder hablar con el API Server de Kubernetes desde el cliente kubectl en este ejemplo:

Contenedor kind-control-plane

Por otro lado ha añadido en el archivo ${HOME}/.kube/config la configuración para conectarnos a este. En el momento que se crea el clúster ya se configura tu contexto para que esté apuntando al mismo, por lo que puedes lanzar el siguiente comando:

kubectl get nodes

Y comprobarás que ahora estás trabajando con tu clúster generado por kind.

Un solo nodo para el clúster de kind

Nota: si estás trabajando con Docker Desktop se recomienda configurar este para que haga uso de 6GB de RAM, recomendados 8GB.

Puedes crear múltiples clústeres si así fuera necesario. Lo único que debes hacer es añadir al comando kind cluster create el parámetro –name para ponerles nombres identificativos.

kind create cluster --name returngis

En el comando por defecto, el nombre del clúster es kind, por lo que si no asignas ningún nombre en los siguientes te dará un error, porque intentará crear uno con el mismo nombre:

Error al intentar un segundo clúster si no especificas un nombre

Crear un clúster con más de un nodo

Como ya has visto, sin más configuración que el comando create cluster, lo que se crea por defecto solo tiene un nodo. Sin embargo es posible añadir más de uno si utilizamos una configuración como esta (también puedes añadir más de un control plane para simular alta disponibilidad):

# three node (two workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker

Para poder aplicar esta configuración es necesario añadir al comando anterior el parámetro –config y el nombre del archivo donde lo has guardado:

kind create cluster --name multi-node --config=multi-node.yaml

Si ahora compruebas el número de nodos de este clúster verás la siguiente salida:

cluster multi-nodo con kind

Aplicaciones con imágenes remotas

Ahora que ya sabes cómo crear clusters con uno o más nodos, es el momento de probar cómo trabajar con nuestras aplicaciones. Por ejemplo, si quisiéramos probar una aplicación con una imagen en Docker Hub como lo siguiente:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web-nginx
  name: web-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata:
      labels:
        app: web-nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: web-nginx
spec:
  selector:
    app: web-nginx
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080

Necesitamos crear un clúster con algunas opciones extra, con el fin de exponer los puertos que esta necesita, para poder acceder a ella desde fuera. En este caso la configuración podría ser la siguiente:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30070

Para que se vea claro, en el host voy a decir que cuando se acceda a través dehttp://localhost:30070 lo que va a pasar es que se va a redirigir al contenedor que está haciendo de clúster, kind-control-plane, y este a su vez se lo va a enviar a aquel contenedor dentro de su clúster que esté escuchando por el puerto 30080.

Al igual que en el caso anterior, para crear un clúster con esta configuración necesitas utilizar el parámetro –config:

kind create cluster --config=config-with-port-mapping.yaml

Ahora, si haces un docker ps verás que tu contenedor de docker expone el puerto indicado en la configuración, el 30070, y que este lo redirige internamente al 30080.

kind mapea puertos al contenedor que hace de cluster

Si lanzas el yaml del servidor web anterior.

kubectl create -f nginx.yaml

Ahora podrás acceder al servicio a través de http://localhost:30070 de tu local.

Aplicaciones con imágenes en local

Otra de los escenarios que nos puede ocurrir es que queramos probar dentro del clúster una imagen que estamos desarrollando en local, como por ejemplo esta:

FROM nginx

COPY index.html /usr/share/nginx/html/

Si la generas de la misma forma que siempre:

docker build -t custom-nginx:v1 .

E intentas usarla para un nuevo despliegue:

kubectl create deploy custom-web --replicas=3 --image=custom-nginx:v1

Al estar en nuestro local, nuestro clúster no es capaz de llegar a ellas si no las ponemos en algún lugar remoto donde este pueda llegar.

kind no llega a las imágenes que están en tu local

La solución de kind es la de cargar dichas imágenes dentro del clúster utilizando el siguiente comando:

kind load docker-image custom-nginx:v1

Para ver cuáles son las imágenes que tienes disponibles en tu clúster puedes verlo ejecutando el comando crictl images dentro del contenedor kind-control-plane en este caso (a no ser que hayas elegido un nombre para tu clúster):

docker exec -it kind-control-plane crictl images

Ahora que ya está la imagen disponible dentro del mismo, los pods ya aparecerán en estado Running.

Existen otras alternativas a esto que te contaré otro día 🙂

¡Saludos!