Módulo 1: Why Kubernetes And The Continuity Challenge
5. Manos a la obra: tu primer clúster
Descripción
Con kind y kubectl instalados (lección 4), esta lección crea el clúster que va a sostener el resto de esta guía: andes-cargo-cluster, con el nombre exacto que aws-serverless-and-containers-guide dejó documentado en ECS y nunca corrió. Todo lo que ves en esta lección corrió de verdad para escribirla — la creación del clúster, la confirmación del plano de control, y el listado final de nodos, todo ejecutado contra Docker real en el momento de escribir esta lección, sin ningún límite de plan de pago ni cuenta de AWS de por medio.
Conexión con el módulo
Esta es la lección que convierte el nombre andes-cargo-cluster de una promesa documentada (la guía anterior) en un clúster real. La lección 6 explica qué acaba de crearse por dentro; la lección 7 carga la imagen heredada dentro de este mismo clúster.
Paso 1 — Define el clúster: kind-config.yaml
kind create cluster, sin ningún argumento, crea un clúster de un solo nodo (que funciona a la vez como plano de control y como lugar donde corren tus cargas de trabajo). Esta guía usa, en cambio, un archivo de configuración explícito desde el principio — un solo plano de control y dos nodos de trabajo (workers) — por una razón pedagógica concreta: la lección 6 explica la diferencia entre el plano de control y los nodos, y esa distinción se entiende mucho mejor cuando existen nodos separados que observar, no un solo contenedor que hace ambos trabajos a la vez.
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: andes-cargo-cluster
nodes:
- role: control-plane
- role: worker
- role: worker
Tres campos merecen explicación antes de usar este archivo:
kind: Cluster— no es el nombre de la herramientakind(aunque coincida) — es el campokindestándar de cualquier manifiesto de la familia Kubernetes, que le dice al sistema qué tipo de objeto está describiendo este documento. Vas a ver este mismo campo, con valores distintos (Pod,Deployment,Service), en cada manifiesto de los módulos siguientes.name: andes-cargo-cluster— el nombre que decidiste reutilizar de la guía anterior (lección 3 de este módulo).kindusa este valor como prefijo de cada contenedor Docker que crea para este clúster.nodes:— la lista explícita de qué "máquinas" quieres dentro del clúster. Un rolcontrol-planey dos rolesworker— cada entrada de esta lista se convierte, literalmente, en un contenedor Docker separado.
Paso 2 — Crea el clúster
kind create cluster --config kind-config.yaml --name andes-cargo-cluster
Fíjate en que
--name andes-cargo-clusterse pasa tanto por línea de comandos como dentro del archivo (name: andes-cargo-cluster) — cuando ambos coinciden, como aquí, no hay ninguna ambigüedad. Si algún día usas unkind-config.yamlsin el camponame, la bandera--namees obligatoria; si el archivo sí lo trae, puedes omitir la bandera ykindusa el valor del archivo.
Qué esperar (literal, ejecutado — el tiempo total varía según tu máquina y tu conexión, pero la secuencia de pasos es siempre la misma):
Creating cluster "andes-cargo-cluster" ...
• Ensuring node image (kindest/node:v1.36.1) 🖼 ...
✓ Ensuring node image (kindest/node:v1.36.1) 🖼
• Preparing nodes 📦 📦 📦 ...
✓ Preparing nodes 📦 📦 📦
• Writing configuration 📜 ...
✓ Writing configuration 📜
• Starting control-plane 🕹️ ...
✓ Starting control-plane 🕹️
• Installing CNI 🔌 ...
✓ Installing CNI 🔌
• Installing StorageClass 💾 ...
✓ Installing StorageClass 💾
• Joining worker nodes 🚜 ...
✓ Joining worker nodes 🚜
Set kubectl context to "kind-andes-cargo-cluster"
You can now use your cluster with:
kubectl cluster-info --context kind-andes-cargo-cluster
Cada línea con un ✓ es una pieza completa de Kubernetes arrancando: la imagen kindest/node:v1.36.1 —el mismo número de versión de Kubernetes (v1.36.1) que confirmaste con kubectl version --client en la lección anterior, no coincidencia— se descarga o se reutiliza de tu caché de Docker; se preparan los tres contenedores (uno por nodo declarado); se instala el CNI (el complemento de red que hace que los Pods puedan hablar entre sí — vuelves a esto a fondo en el Módulo 4); se instala una StorageClass por defecto; y los dos nodos worker se unen al plano de control. La última línea es la más importante de leer con atención: kind ya modificó tu archivo ~/.kube/config, agregando un contexto nuevo llamado kind-andes-cargo-cluster — la pieza exacta que le faltaba a kubectl en la lección 4 para dejar de fallar con "connection refused".
Paso 3 — Confirma el plano de control
kubectl cluster-info --context kind-andes-cargo-cluster
Qué esperar (el puerto exacto —56493 en este caso— es asignado al azar por Docker cada vez que se crea el clúster; marcado como variable. El resto es literal):
Kubernetes control plane is running at https://127.0.0.1:56493
CoreDNS is running at https://127.0.0.1:56493/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Dos líneas, dos confirmaciones distintas: el plano de control (kube-apiserver, la puerta de entrada a todo el clúster — profundizas en esto en la lección 6) está arriba y respondiendo en https://127.0.0.1:<puerto>; y CoreDNS —el servidor de nombres interno del clúster, la pieza que hace posible que un Pod encuentre a otro por nombre en vez de por dirección IP, algo que vas a usar sin pensarlo desde el Módulo 3 en adelante— también está corriendo.
Paso 4 — Confirma los nodos
Justo después de crear el clúster, es normal que los nodos todavía no estén listos — el CNI necesita unos segundos más para terminar de configurarse en cada uno:
kubectl get nodes
Qué esperar (inmediatamente después de crear el clúster — nota el estado NotReady, normal en los primeros segundos):
NAME STATUS ROLES AGE VERSION
andes-cargo-cluster-control-plane NotReady control-plane 20s v1.36.1
andes-cargo-cluster-worker NotReady <none> 5s v1.36.1
andes-cargo-cluster-worker2 NotReady <none> 5s v1.36.1
Espera unos segundos más y corre el mismo comando otra vez:
kubectl get nodes
Qué esperar (literal, ejecutado, unos 20-30 segundos más tarde — los tres nodos en Ready; AGE avanza con el reloj, marcado como variable; NAME, ROLES y VERSION son literales):
NAME STATUS ROLES AGE VERSION
andes-cargo-cluster-control-plane Ready control-plane 29s v1.36.1
andes-cargo-cluster-worker Ready <none> 14s v1.36.1
andes-cargo-cluster-worker2 Ready <none> 14s v1.36.1
Tres nodos, tres nombres construidos a partir del name que declaraste en kind-config.yaml: andes-cargo-cluster-control-plane, andes-cargo-cluster-worker, andes-cargo-cluster-worker2. Ese patrón de nombres —prefijo del clúster, más el rol— es literal y predecible, a diferencia de los nombres de Pod que vas a ver a partir del Módulo 2, que sí llevan un sufijo generado al azar.
Confirma, del lado de Docker, que son contenedores reales
docker ps --filter "name=andes-cargo-cluster" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
Qué esperar (el tiempo exacto de "Up" es variable; el resto, literal):
NAMES IMAGE STATUS
andes-cargo-cluster-worker2 kindest/node:v1.36.1 Up About a minute
andes-cargo-cluster-worker kindest/node:v1.36.1 Up About a minute
andes-cargo-cluster-control-plane kindest/node:v1.36.1 Up About a minute
Esto no es una curiosidad — es el punto central de honestidad de esta guía, y lo vas a retomar a fondo en la lección 6: cada "nodo" que kubectl get nodes te mostró como parte de un clúster de Kubernetes es, literalmente, un contenedor Docker corriendo en tu máquina, visible con el mismo docker ps que ya conoces de docker-essentials-guide y de la guía anterior.
Analogía: la maqueta a escala del estadio
Piensa en este clúster kind como una maqueta a escala de un estadio de fútbol, construida para ensayar antes del partido real. No es una simulación de cartón — está hecha de los mismos materiales de construcción (concreto, acero) que el estadio grande, solo que en un tamaño que cabe en una mesa de trabajo. Cada pieza que vas a instalar sobre este clúster durante el resto de la guía —el campo de juego (los Pods), los túneles de acceso (Ingress), el sistema de seguridad en las puertas (admission control)— se comporta exactamente igual que se comportaría en el estadio de producción completo (EKS, Módulo 7). La diferencia entre la maqueta y el estadio real no está en los materiales — está en quién construyó y mantiene la estructura alrededor: aquí, la construiste tú mismo con kind create cluster; en EKS, AWS administra esa parte por ti, con las implicaciones de costo y de control que el Módulo 7 explica a fondo.
Profundización: qué significa "contexto" en kubectl
kubectl cluster-info --context kind-andes-cargo-cluster usó un argumento que vale la pena entender antes de seguir: un contexto, en kubectl, es una combinación con nombre de tres cosas — a qué clúster conectarte, con qué usuario/credenciales, y en qué namespace por defecto trabajar. kind crea automáticamente un contexto llamado kind-<nombre-del-clúster> cada vez que creas un clúster nuevo, y lo deja como el contexto activo — por eso, a partir de ahora, puedes omitir --context en la mayoría de los comandos de esta guía, y kubectl va a asumir que quieres hablar con andes-cargo-cluster. Puedes confirmar cuál es tu contexto activo en cualquier momento:
kubectl config current-context
Qué esperar:
kind-andes-cargo-cluster
Este mecanismo de contextos es exactamente lo que te va a permitir, más adelante en tu carrera, tener configurado en el mismo ~/.kube/config tanto este clúster kind local como un clúster EKS real, y cambiar entre ambos con kubectl config use-context sin reinstalar nada.
Errores comunes
Correr kind create cluster una segunda vez con el mismo nombre, sin darse cuenta (de flujo). Qué pasa: alguien, después de ya haber creado andes-cargo-cluster en un intento anterior, vuelve a correr el mismo comando de esta lección, y kind responde con un error indicando que ya existe un clúster con ese nombre. Por qué pasa: es fácil perder de vista qué clústeres ya tienes creados, sobre todo si volviste a esta lección después de una pausa. Cómo detectarlo: el mensaje de error de kind menciona explícitamente node(s) already exist for a cluster with the name "andes-cargo-cluster". Cómo corregirlo: confirma primero con kind get clusters qué clústeres ya existen; si andes-cargo-cluster ya está en la lista, no necesitas crearlo de nuevo — simplemente sigue con el Paso 3 de esta lección para confirmar que sigue sano.
Interpretar NotReady inmediatamente después de crear el clúster como un fallo (conceptual, el más común de esta lección específica). Qué pasa: alguien corre kubectl get nodes en el instante exacto en que termina kind create cluster, ve STATUS: NotReady en los tres nodos, y asume que algo salió mal. Por qué pasa: "NotReady" suena a un estado de error, no a un estado transitorio normal. Cómo detectarlo: si el estado sigue en NotReady después de más de un minuto completo, ahí sí hay un problema real que investigar (revisa docker ps para confirmar que los tres contenedores siguen corriendo); si pasaron solo unos segundos, es exactamente el comportamiento esperado. Cómo corregirlo: esta lección lo muestra de forma explícita — el CNI necesita unos segundos para terminar de configurarse en cada nodo antes de que reporte Ready. Espera y vuelve a correr kubectl get nodes.
No notar que kind create cluster cambió el contexto activo de kubectl, y confundirse si ya tenías otro clúster configurado (de configuración, relevante para quien llega con experiencia previa en Kubernetes). Qué pasa: alguien que ya tenía otro clúster (por ejemplo, uno de un proyecto personal anterior) configurado en su ~/.kube/config, corre los comandos de esta lección, y después se sorprende de que sus comandos de kubectl en otro proyecto ahora apunten a andes-cargo-cluster en vez de al clúster que esperaba. Por qué pasa: kind create cluster deja el contexto nuevo como el activo por defecto — un comportamiento conveniente para esta guía, pero que puede sorprender a quien tiene múltiples clústeres. Cómo detectarlo: kubectl config current-context muestra kind-andes-cargo-cluster cuando esperabas otro nombre. Cómo corregirlo: usa kubectl config get-contexts para ver todos los contextos disponibles, y kubectl config use-context <nombre> para cambiar entre ellos — nada se borró, solo cambió cuál es el contexto activo.
Ejercicios
Ejercicio 1 — Explica kind-config.yaml sin mirarlo. Sin volver al Paso 1, escribe de memoria los tres campos principales de este archivo y qué controla cada uno.
Ver solución
kind: Cluster — declara qué tipo de objeto describe el archivo (un clúster completo, no un nodo individual ni ningún otro tipo de recurso). name: andes-cargo-cluster — el nombre del clúster, usado como prefijo para cada contenedor Docker que kind crea. nodes: — la lista explícita de nodos que quieres, con su rol (control-plane o worker); cada entrada de esta lista se convierte en un contenedor Docker separado.
Ejercicio 2 — Predice el número de contenedores. Si cambiaras kind-config.yaml para tener un control-plane y cuatro worker, ¿cuántos contenedores Docker esperarías ver con docker ps --filter "name=andes-cargo-cluster" después de crear el clúster?
Ver solución
Cinco — uno por cada entrada declarada en la lista nodes: (un control-plane más cuatro worker), porque cada nodo declarado en el archivo de configuración se convierte, literalmente, en un contenedor Docker independiente. Este es exactamente el punto que la lección 6 desarrolla a fondo: "un nodo de Kubernetes" y "un contenedor Docker" son, en kind, la misma cosa vista desde dos capas distintas.
Ejercicio 3 — Diagnostica un contexto inesperado. Un compañero corre kubectl get pods después de seguir esta lección, y obtiene un error sobre un clúster que no reconoce, con un nombre que no es kind-andes-cargo-cluster. ¿Qué comando usarías primero para diagnosticar el problema, y qué comando lo corregiría?
Ver solución
Primero, kubectl config current-context — para confirmar cuál es el contexto activo en este momento. Si el resultado no es kind-andes-cargo-cluster, el compañero probablemente tiene otro clúster configurado que quedó como activo (por ejemplo, si creó otro clúster de kind después de este, o si tenía un contexto de otro proyecto ya activo). El comando que lo corrige es kubectl config use-context kind-andes-cargo-cluster, que cambia el contexto activo sin borrar ninguna configuración existente de otros clústeres.
Resumen y siguiente paso
En esta lección creaste, de verdad, tu primer clúster de Kubernetes: andes-cargo-cluster, con un plano de control y dos nodos de trabajo, corriendo Kubernetes v1.36.1 dentro de tres contenedores Docker separados en tu propia máquina. Confirmaste el plano de control con kubectl cluster-info, confirmaste los tres nodos en estado Ready con kubectl get nodes, y viste, del lado de Docker, que cada "nodo" es literalmente un contenedor más en tu docker ps. Este es, textualmente, el clúster que aws-serverless-and-containers-guide prometió y nunca pudo correr — ahora existe.
Antes de avanzar deberías poder: explicar los tres campos principales de kind-config.yaml; distinguir un estado NotReady transitorio normal de un problema real; y usar kubectl config current-context/use-context para diagnosticar a qué clúster está hablando kubectl en un momento dado.
La lección 6 abre la caja de este clúster: qué es exactamente el plano de control, qué hace etcd, y por qué cada componente que acabas de crear corre como un contenedor Docker más, sin ninguna magia adicional.
Recursos
- kind — Quick Start — la guía oficial, incluida la sintaxis exacta de
kind create cluster --config. - kind — Configuration — referencia completa del formato
kind-config.yaml, incluidos los rolescontrol-planeyworker. - Kubernetes —
kubectlCheat Sheet — referencia oficial de comandos, incluidoscluster-infoyconfig current-context. - Kubernetes — Configure Access to Multiple Clusters — la documentación oficial sobre contextos, la pieza que resuelve el tercer error común de esta lección.