Saltar al contenido

Construir un cluster de Kubernetes en Google Cloud Platform con kubeadm

Publicado 8 min de lectura
Diagrama de arquitectura de Kubernetes en GCP

¿Alguna vez te preguntaste cómo funcionan realmente los clusters de Kubernetes por debajo? En esta guía te voy a acompañar paso a paso para que construyas tu propio cluster de Kubernetes en Google Cloud Platform desde cero usando kubeadm. Esta experiencia práctica te va a dar una comprensión más profunda de la arquitectura de Kubernetes y te va a ayudar a apreciar lo que servicios administrados como GKE hacen detrás de escena.

Ya sea que estés preparando una certificación, armando tu homelab, o simplemente tengas curiosidad sobre la orquestación de contenedores, este tutorial paso a paso te tiene cubierto.

Lo que vas a necesitar

Tranquilo—la configuración es simple. Esto es lo que necesitás antes de arrancar:

  • Cuenta de Google Cloud: necesitás una cuenta de GCP activa con facturación habilitada. Si sos nuevo en GCP, ofrecen créditos gratuitos para arrancar.
  • gcloud CLI: el Google Cloud SDK en tu máquina local (conseguilo acá)
    • Configuración rápida: gcloud auth login para autenticarte
  • Permisos apropiados: tu cuenta de GCP debe poder:
    • Crear y administrar proyectos
    • Levantar instancias de Compute Engine
    • Configurar redes VPC y reglas de firewall
  • Cierta familiaridad con:
    • Comandos básicos de Linux
    • Conexiones SSH
    • Fundamentos de Kubernetes (aunque vamos a ir explicando sobre la marcha)

Manos a la obra

¿Listo para ensuciarte las manos? Vamos a construir este cluster paso a paso, empezando por la infraestructura y subiendo hasta tener un cluster completamente funcional. Te voy a explicar qué hace cada comando y por qué importa.

Paso 1: Configurar tu proyecto de GCP

Lo primero es lo primero—creemos un proyecto de GCP dedicado para nuestro cluster y hagámoslo el proyecto activo. Ejecutá estos comandos en tu máquina local:

gcloud projects create my-k8s-cluster
gcloud config set project my-k8s-cluster

Paso 2: Armar tu infraestructura de red

Configurá una red VPC personalizada con ruteo BGP regional y creá una subred en la región us-central1. Ejecutá estos comandos en tu máquina local:

gcloud compute networks create k8s-vpc \
  --subnet-mode=custom \
  --bgp-routing-mode=regional
 
gcloud compute networks subnets create k8s-subnet \
  --network=k8s-vpc \
  --range=10.0.0.0/24 \
  --region=us-central1

Paso 3: Blindar la seguridad con reglas de firewall

Configurá reglas de firewall para habilitar acceso SSH desde cualquier lado y permitir toda la comunicación interna entre los nodos del cluster. Ejecutá estos comandos en tu máquina local:

gcloud compute firewall-rules create k8s-allow-ssh \
  --network=k8s-vpc \
  --allow=tcp:22 \
  --source-ranges=0.0.0.0/0
 
gcloud compute firewall-rules create k8s-allow-internal \
  --network=k8s-vpc \
  --allow=tcp,udp,icmp

Paso 4: Levantar tu nodo de control plane

Aprovisioná una instancia e2-medium con Ubuntu 22.04 LTS para que funcione como el control plane del cluster. Ejecutá este comando en tu máquina local:

gcloud compute instances create k8s-control-plane \
  --machine-type=e2-medium \
  --subnet=k8s-subnet \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud \
  --zone=us-central1-a

Paso 5: Entrar a tu control plane

Conectate a la VM del control plane usando el CLI de gcloud. Ejecutá este comando en tu máquina local:

gcloud compute ssh k8s-control-plane --zone=us-central1-a

Paso 6: Preparar el entorno del control plane

Instalar containerd en Ubuntu para un cluster de Kubernetes requiere algunos ajustes específicos a nivel de sistema operativo antes de la instalación en sí, para asegurar que el networking y la administración de recursos (cgroups) funcionen correctamente.

Acá va la guía paso a paso para dejarlo funcionando. Todos los comandos de esta sección se ejecutan en el nodo del control plane.

Prerrequisitos de configuración del sistema

Kubernetes necesita módulos de kernel y configuraciones de red específicas para que el runtime de contenedores pueda manejar tráfico con bridging.

Cargar módulos de kernel

Creá un archivo de configuración para cargar los módulos necesarios al arrancar (en el control plane):

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
 
sudo modprobe overlay
sudo modprobe br_netfilter

Configurar Sysctl

Habilitá el reenvío de IP y el networking con bridge. El comando sysctl aplica estos cambios de inmediato, sin necesidad de reiniciar (en el control plane):

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
 
sudo sysctl --system

Instalar containerd

Podés instalar containerd directamente desde los repositorios oficiales de Ubuntu (en el control plane):

sudo apt update
sudo apt install -y containerd

Configurar containerd para Kubernetes

Este es el paso más crítico. Por defecto, containerd no usa el driver de cgroup de systemd, que Kubernetes recomienda fuertemente para mayor estabilidad.

Generar la configuración por defecto

Creá el directorio y generá un archivo de configuración limpio (en el control plane):

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

Habilitar el driver de cgroup de systemd

Necesitás cambiar SystemdCgroup = false por true. Podés hacerlo manualmente con un editor o usar este comando sed (en el control plane):

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

Reiniciar containerd

Aplicá la nueva configuración (en el control plane):

sudo systemctl restart containerd
sudo systemctl enable containerd

Instalar kubeadm, kubelet y kubectl

Agregá el repositorio de paquetes de Kubernetes e instalá los componentes necesarios. Tené en cuenta que el directorio /etc/apt/keyrings normalmente ya está presente en los sistemas Ubuntu 22.04. Los paquetes quedan marcados como retenidos para evitar actualizaciones automáticas (en el control plane):

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
 
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
 
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
 
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
 
sudo systemctl enable --now kubelet

Paso 7: Iniciar el control plane de Kubernetes

Inicializá el control plane de Kubernetes con el rango de CIDR de red de pods especificado (en el control plane):

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Una vez que la inicialización termine con éxito, configurá el acceso de kubectl para tu usuario (en el control plane):

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

La inicialización va a mostrar un token de join para agregar nodos worker. Podés guardarlo, aunque generar uno nuevo más adelante es igual de simple.

Desplegar tu plugin de red de pods

Desplegá Flannel como plugin CNI (Container Network Interface) para habilitar la comunicación pod-a-pod en todo el cluster (en el control plane):

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Potenciar tu experiencia con kubectl

Habilitá el autocompletado de comandos de kubectl para la sesión actual y persistilo para sesiones futuras. El primer comando lo activa de inmediato, y el segundo lo agrega a tu perfil de bash (en el control plane):

source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

De forma opcional, creá un alias k para kubectl con el mismo comportamiento de autocompletado (en el control plane):

alias k=kubectl
complete -o default -F __start_kubectl k

Paso 8: Sumar nodos worker a la mezcla

Con el control plane listo, aprovisioná una instancia de VM adicional que va a funcionar como nodo worker para correr las cargas de trabajo. Ejecutá este comando en tu máquina local:

gcloud compute instances create k8s-worker-1 \
  --machine-type=e2-medium \
  --subnet=k8s-subnet \
  --image-family=ubuntu-2204-lts \
  --image-project=ubuntu-os-cloud \
  --zone=us-central1-a

Paso 9: Entrar a tu nodo worker

Conectate a la VM del nodo worker usando el CLI de gcloud. Ejecutá este comando en tu máquina local:

gcloud compute ssh k8s-worker-1 --zone=us-central1-a

Paso 10: Preparar el entorno del nodo worker

Todos los comandos de esta sección se ejecutan en el nodo worker. Repetí todos los pasos de instalación del Paso 6 en el nodo worker: prerrequisitos de configuración del sistema, instalar containerd, configurar containerd para Kubernetes, e instalar kubeadm, kubelet y kubectl.

Paso 11: Sumar el worker al control plane

Generá un comando de join nuevo desde el control plane (en el control plane):

kubeadm token create --print-join-command

Ejecutá el comando de la salida en el nodo worker para registrarlo en el cluster (en el nodo worker).

Paso 12: Ponele a prueba tu cluster

Ahora que tu cluster está completamente operativo, verificá que todo funcione desplegando un servidor web nginx simple. Todos los comandos kubectl se ejecutan en el control plane.

Crear y correr un pod de nginx

Desplegá un pod de nginx en tu cluster (en el control plane):

kubectl run nginx-test --image=nginx:latest --port=80

Verificar que el pod esté corriendo

Revisá el estado de tu pod (en el control plane):

kubectl get pods

Deberías ver una salida similar a esta:

NAME         READY   STATUS    RESTARTS   AGE
nginx-test   1/1     Running   0          30s

Obtener información detallada del pod

Mirá más detalles sobre el pod en ejecución (en el control plane):

kubectl describe pod nginx-test

Exponer el pod al mundo

Si querés acceder a nginx desde adentro del cluster, creá un service (en el control plane):

kubectl expose pod nginx-test --type=NodePort --port=80

Revisá el service y el puerto asignado (en el control plane):

kubectl get services nginx-test

Acceder a nginx desde tu computadora

Para acceder al servidor nginx desde tu máquina local, vas a necesitar abrir el NodePort en el firewall de GCP y conseguir la IP externa de uno de tus nodos.

Primero, creá una regla de firewall para permitir tráfico en el rango de NodePort (30000-32767), ejecutá esto en tu máquina local:

gcloud compute firewall-rules create k8s-allow-nodeport \
  --network=k8s-vpc \
  --allow=tcp:30000-32767 \
  --source-ranges=0.0.0.0/0

Conseguí la dirección IP externa de tu nodo worker o del control plane (en tu máquina local):

gcloud compute instances list --filter="name~'k8s-'"

Anotá el EXTERNAL_IP de la salida. Ahora conseguí el NodePort asignado a tu service (en el control plane):

kubectl get service nginx-test -o jsonpath='{.spec.ports[0].nodePort}'

Esto va a mostrar un número de puerto entre 30000 y 32767. Accedé a nginx abriendo en tu navegador:

http://EXTERNAL_IP:NODEPORT

Por ejemplo, si tu IP externa es 34.123.45.67 y el NodePort es 31234, visitá:

http://34.123.45.67:31234

Deberías ver la página "Welcome to nginx!".

Limpiar los recursos de prueba

Eliminá el pod y el service de nginx cuando termines de probar (en el control plane):

kubectl delete service nginx-test
kubectl delete pod nginx-test

Si creaste la regla de firewall de NodePort, eliminala también (en tu máquina local):

gcloud compute firewall-rules delete k8s-allow-nodeport

Paso 13: Desarmar tu cluster

Desarmá todos los recursos creados en orden inverso. Empezá por las VMs, y después eliminá las reglas de firewall, la subred y la VPC. Ejecutá estos comandos en tu máquina local:

gcloud compute instances delete k8s-control-plane k8s-worker-1 \
  --zone=us-central1-a
 
gcloud compute firewall-rules delete k8s-allow-ssh k8s-allow-internal
 
gcloud compute networks subnets delete k8s-subnet \
  --region=us-central1
 
gcloud compute networks delete k8s-vpc

Si querés eliminar el proyecto entero y todo su contenido, ejecutá:

gcloud projects delete my-k8s-cluster

Una palabra sobre estar listo para producción

Antes de cerrar, tengamos una conversación honesta: este cluster es perfecto para aprender y hacer pruebas, pero no está listo para producción. Pensalo como tu terreno de entrenamiento—un espacio seguro para experimentar, romper cosas y aprender.

Reflexión final

¡Felicitaciones por construir tu propio cluster de Kubernetes! Ganaste experiencia práctica en orquestación de contenedores que muchos desarrolladores nunca llegan a tener. Usá esta configuración para experimentar, probar tus aplicaciones, y profundizar tu comprensión de cómo funciona Kubernetes en la realidad.

Cuando estés listo para producción, vas a apreciar todavía más los servicios administrados—pero también vas a entender qué está pasando detrás de escena. Y ese conocimiento no tiene precio.

¡Feliz clustering! Si tenés preguntas o querés compartir tu experiencia, escribime. Sigamos aprendiendo juntos.