Deployment y ciclo de vida
Del Pod al Deployment
En el módulo anterior aprendiste algo incómodo: si un Pod cae y nadie lo recrea, ahí se acaba la historia. En producción nadie despliega Pods sueltos. Se despliegan Deployments: un objeto que declara cuántas réplicas de un Pod deben existir y qué plantilla siguen, y que se encarga de crearlas, reemplazarlas cuando cambia la versión y volver atrás cuando algo sale mal.
Por debajo, el Deployment no gestiona los Pods directamente: crea un ReplicaSet por cada versión de la plantilla, y es el ReplicaSet quien mantiene el número de réplicas. Lo verás con tus propios ojos en esta lección. Abre la pestaña dev-machine y, si quieres ver el árbol de objetos en directo, la pestaña Explorer.
Paso 1: Crea el Deployment
Crea un archivo deployment.yaml con este contenido:
cat << 'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: ghcr.io/iximiuz/labs/nginx:alpine
ports:
- containerPort: 80
EOF
El YAML, explicado con preguntas y respuestas
Ya conoces metadata, labels y el contenido de containers de la primera lección, así que las preguntas se centran en lo nuevo.
¿Por qué apiVersion ahora es apps/v1 y no v1?
Los Deployments no pertenecen al grupo core de la API sino al grupo apps, que agrupa los objetos de cargas de trabajo (Deployments, ReplicaSets, StatefulSets, DaemonSets). El formato es <grupo>/<versión>.
¿Qué declara replicas?
El número de Pods idénticos que deben existir en todo momento. Si un Pod cae, el ReplicaSet crea otro; si sobran, elimina. Es el ejemplo perfecto de estado deseado frente a estado real.
¿Para qué sirve selector.matchLabels?
Es el pegamento del Deployment: define qué Pods considera suyos. Debe coincidir con las labels de la plantilla, y desde apps/v1 es obligatorio e inmutable. Si no coincidiera con template.metadata.labels, la API rechazaría el objeto.
¿Qué es template exactamente?
Un Pod completo embebido, con su metadata y su spec. Compáralo con el pod.yaml de la primera lección: es lo mismo, solo que sin nombre, porque los nombres de los Pods los genera el ReplicaSet (verás sufijos aleatorios como web-7d4b9c8f6d-x2klp).
¿Entonces hay tres capas de labels en este archivo?
Sí, y conviene distinguirlas: las labels del propio Deployment (organizativas), el selector (funcional, elige Pods) y las labels de la plantilla (las que llevarán los Pods creados). Las dos últimas deben coincidir.
Aplícalo y observa lo que aparece:
kubectl apply -f deployment.yaml
kubectl get deployments,replicasets,pods -l app=web
Fíjate en la cadena: el Deployment web ha creado un ReplicaSet con un sufijo, y ese ReplicaSet ha creado 3 Pods con otro sufijo más.
Antes de seguir, comprueba la promesa de la autorreparación: borra uno de los Pods con kubectl delete pod <nombre> y ejecuta kubectl get pods -l app=web inmediatamente. Verás aparecer un sustituto en segundos. Esto es lo que un Pod suelto no podía darte.
Paso 2: Escala a 5 réplicas
Puedes hacerlo de forma imperativa:
kubectl scale deployment web --replicas=5
O de forma declarativa, cambiando replicas: 5 en el archivo y aplicando de nuevo. Ambas son válidas; la declarativa deja el cambio registrado en tu YAML, que es lo que querrás en un repositorio.
Paso 3: Despliega una nueva versión (rollout)
Cualquier cambio en la template del Deployment dispara un rollout: el Deployment crea un ReplicaSet nuevo con la plantilla nueva y va moviendo réplicas del viejo al nuevo de forma gradual (estrategia RollingUpdate). Vas a simular una nueva versión añadiendo una variable de entorno a la plantilla:
kubectl set env deployment/web VERSION=2
Y ahora, rápido, observa el baile en directo:
kubectl rollout status deployment/web
kubectl get rs -l app=web
Verás dos ReplicaSets: el antiguo reduciéndose hasta 0 y el nuevo creciendo hasta 5. El antiguo no se borra: es el historial que hace posible el rollback.
💡 En un caso real el cambio sería la imagen (kubectl set image deployment/web nginx=registro/app:v2). Usamos una variable de entorno porque dispara exactamente el mismo mecanismo y no depende de que exista un segundo tag en el registro.
Paso 4: Deshaz el cambio (rollback)
Imagina que la versión 2 ha resultado ser un desastre. Consulta el historial y vuelve atrás:
kubectl rollout history deployment/web
kubectl rollout undo deployment/web
El rollback no borra nada: crea una revisión nueva cuya plantilla es la de la revisión anterior. Compruébalo en el historial cuando termine.
Resumen
- Un Deployment declara réplicas y plantilla; un ReplicaSet por versión las mantiene.
- Escalar es cambiar un número; Kubernetes hace el resto.
- Todo cambio de plantilla dispara un rollout gradual que no tira el servicio.
- El historial de ReplicaSets hace el rollback instantáneo y seguro.
Te queda ponerlo a prueba sin red: en la siguiente unidad te espera un rollout atascado de verdad.
Challenge: rollout atascado
Acabas de practicar el rollout y el rollback en condiciones de laboratorio. Este challenge los pone en su contexto natural: una incidencia.
Un Deployment de producción lleva media hora con el rollout atascado porque la imagen de la nueva versión no existe en el registro. La estrategia RollingUpdate ha protegido el servicio a medias, con los Pods antiguos aguantando el tráfico, pero hay que recuperar el estado anterior. Diagnóstico y rollout undo, como en la vida real.
Criterio de superación: el Deployment tienda vuelve a la imagen buena mediante rollback, con 3/3 réplicas ready y ningún Pod roto. Al completarlo, la lección queda superada.
- Previous lesson
- Challenge: recursos y estado
- Next lesson
- StatefulSet