Curso Profesional de DevOps

Toma las primeras clases gratis

⏱ Tiempo estimado: 25 minutos

🎯 Rama / Perfil: Devs y DevOps que dan el paso de Docker a orquestación.

🧠 Conocimiento previo necesario: Clases 2, 3, 13 y 15 del curso (Docker y estrategias Blue/Green, Canary y Rolling).

💡 ¿Qué vas a lograr? Actualizar una app en un clúster local sin downtime, romper un despliegue a propósito y recuperarte con un comando.

🛠 Lo que necesitas antes de empezar

📋 Pasos

Paso 1: Crea el clúster y la app

bash

kind create cluster --name lab

En una carpeta nueva, crea server.js:

js

const http = require('http');
http.createServer((req, res) => {
  if (req.url === '/healthz') return res.end('ok');
  res.end('Hola desde la version ' + process.env.APP_VERSION + '\n');
}).listen(3000);

Y Dockerfile:

dockerfile

FROM node:20-alpine
WORKDIR /app
COPY server.js .
ARG APP_VERSION=1
ENV APP_VERSION=$APP_VERSION
CMD ["node", "server.js"]

Paso 2: Construye dos versiones y cárgalas al clúster

bash

docker build --build-arg APP_VERSION=1 -t web:v1 .
docker build --build-arg APP_VERSION=2 -t web:v2 .
kind load docker-image web:v1 web:v2 --name lab

kind load copia las imágenes locales dentro del clúster, así que no necesitas un registry.

Paso 3: Despliega 3 réplicas con estrategia Rolling

Crea deploy.yaml:

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
        - name: web
          image: web:v1
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet: { path: /healthz, port: 3000 }
            initialDelaySeconds: 2
            periodSeconds: 2
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector: { app: web }
  ports:
    - port: 80
      targetPort: 3000

bash

kubectl apply -f deploy.yaml
kubectl rollout status deployment/web

maxUnavailable: 0 garantiza que nunca baje la capacidad durante la actualización, y el readinessProbe evita enviar tráfico a un pod que aún no responde. 🔗 Referencia: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

Paso 4: Actualiza a v2 sin downtime

Abre una segunda terminal y lanza un cliente que consulte el Service sin parar:

bash

kubectl run curl --rm -it --image=curlimages/curl --restart=Never -- \
  sh -c 'while true; do curl -s web; sleep 0.5; done'

En la primera terminal:

bash

kubectl set image deployment/web web=web:v2
kubectl rollout status deployment/web

Verás cómo las respuestas pasan de “version 1” a “version 2” sin errores ni cortes.

Paso 5: Rompe un despliegue a propósito

bash

kubectl set image deployment/web web=web:v9
kubectl rollout status deployment/web --timeout=30s
kubectl get pods

La imagen web:v9 no existe, así que los pods nuevos quedan en ErrImagePull o ImagePullBackOff. Observa en la segunda terminal que tu app sigue respondiendo con v2: Kubernetes no retiró los pods sanos porque los nuevos nunca estuvieron Ready.

Paso 6: Haz rollback

bash

kubectl rollout undo deployment/web
kubectl rollout status deployment/web
kubectl rollout history deployment/web

Todo vuelve a un estado sano en segundos. Cuando termines, limpia con kind delete cluster --name lab.

✅ Resultado esperado

Un clúster local con 3 réplicas de tu app, una actualización a v2 con cero cortes (comprobada con tráfico continuo) y un despliegue roto contenido y revertido con rollout undo.

🔥 Tu reto (siguiente acción)

Cambia el readinessProbe para que apunte a una ruta que no existe (por ejemplo /nope) y predice qué pasará con el rollout antes de aplicarlo. Luego intenta una variante canary manual: crea un segundo Deployment con 1 réplica de v2 detrás del mismo Service y compara cómo se reparte el tráfico.

📚 Recursos para ir más lejos

Curso Profesional de DevOps

Toma las primeras clases gratis

0 Comentarios

para escribir tu comentario

Artículos relacionados