Módulo 3: Configuration Secrets Health And Autoscaling
6. Manos a la obra: `probes` reales sobre `status-api-service`
Descripción
Esta es la lección donde andes-cargo-status-api recibe sus tres sondas de salud, y donde vas a provocar —a propósito, de forma controlada y reversible— exactamente los dos fallos que la lección 5 describió en teoría: un Pod que sale del Service sin reiniciarse, y un Pod que se reinicia de verdad. Nada de esto se simula: vas a editar la configuración de las sondas para inducir cada fallo, observar la consecuencia real con kubectl get pods/kubectl describe, y revertir cada cambio antes de seguir. Todo lo que sigue corrió contra andes-cargo-cluster.
Conexión con el módulo
Esta lección cierra la segunda de las tres piezas de este módulo con evidencia real, exactamente como la lección 4 cerró la primera. La lección 7 agrega la tercera —capacidad elástica— sobre este mismo Deployment, ahora con configuración y salud resueltas.
Paso 1 — Agrega las tres sondas al Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: andes-cargo-status-api
namespace: andes-cargo
labels:
app: andes-cargo-status-api
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: andes-cargo-status-api
template:
metadata:
labels:
app: andes-cargo-status-api
spec:
containers:
- name: andes-cargo-status-api
image: andes-cargo-status-api:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: andes-cargo-status-api-config
- secretRef:
name: andes-cargo-status-api-secrets
startupProbe:
httpGet:
path: /health
port: 8080
periodSeconds: 5
failureThreshold: 6
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 1
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
Dos cosas nuevas frente al deployment.yaml de la lección 4: las tres sondas (todas contra /health, como recomendó la lección 5), y strategy.rollingUpdate explícito, con maxSurge: 1/maxUnavailable: 0 — esto le dice a Kubernetes "nunca bajes de 3 réplicas disponibles durante un despliegue, y agrega como máximo 1 Pod extra a la vez". Vas a usar esta configuración a propósito en los siguientes pasos: te va a permitir inducir un fallo sobre un Pod nuevo, sin arriesgar ni un segundo de disponibilidad de los tres Pods existentes, que siguen atendiendo tráfico real todo el tiempo.
Aplica el cambio, con failureThreshold: 6 (startupProbe) dando margen de sobra para que Flask arranque —en la práctica, arranca en menos de un segundo, así que esta sonda nunca vas a verla fallar en esta guía—:
kubectl apply -f deployment.yaml
kubectl rollout status deployment/andes-cargo-status-api -n andes-cargo --timeout=60s
Qué esperar (literal, ejecutado):
deployment.apps/andes-cargo-status-api configured
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 old replicas are pending termination...
deployment "andes-cargo-status-api" successfully rolled out
Confirma que las tres sondas quedaron configuradas exactamente como las declaraste:
kubectl describe pod <un-pod-tuyo> -n andes-cargo | grep -A3 "Liveness:\|Readiness:\|Startup:"
Qué esperar (literal — Kubernetes muestra los parámetros de cada sonda en una sola línea legible):
Liveness: http-get http://:8080/health delay=5s timeout=3s period=5s #success=1 #failure=3
Readiness: http-get http://:8080/health delay=2s timeout=3s period=5s #success=1 #failure=1
Startup: http-get http://:8080/health delay=0s timeout=1s period=5s #success=1 #failure=6
Confirma también que los tres Pods están sanos y en la lista de Endpoints del Service:
kubectl get endpoints status-api-service -n andes-cargo
Qué esperar (tres IPs — las tuyas van a ser distintas):
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
NAME ENDPOINTS AGE
status-api-service 10.244.1.7:8080,10.244.2.8:8080,10.244.2.9:8080 23m
Esta es tu línea base: tres Pods, tres Endpoints, cero RESTARTS. Todo lo que sigue se compara contra esta foto.
Paso 2 — Induce un fallo de readiness
Una readinessProbe no se puede editar en un Pod ya corriendo —es un campo inmutable del spec del contenedor—, así que para provocar un fallo real, vas a cambiar la ruta de la sonda en el Deployment. Con maxSurge: 1/maxUnavailable: 0, esto crea exactamente un Pod nuevo con la sonda rota, mientras tus tres Pods sanos siguen atendiendo tráfico sin ninguna interrupción:
kubectl patch deployment andes-cargo-status-api -n andes-cargo --type=json \
-p '[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/readyz-check"}]'
/readyz-check no existe en app.py —a propósito—, así que cualquier solicitud a esa ruta va a responder 404, y Kubernetes va a contar eso como un fallo de la sonda.
Qué esperar:
deployment.apps/andes-cargo-status-api patched
Observa lo que pasa en los siguientes segundos:
kubectl get pods -n andes-cargo -l app=andes-cargo-status-api -o wide
Qué esperar (literal, ejecutado ~20 segundos después del patch — los tres Pods viejos, sin tocar, siguen 1/1 Running; el Pod nuevo queda atascado en 0/1, Running, con RESTARTS: 0):
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
andes-cargo-status-api-65fcd6f6c8-2bkht 1/1 Running 0 5m43s 10.244.1.7 andes-cargo-cluster-worker2 <none> <none>
andes-cargo-status-api-65fcd6f6c8-cnbjw 1/1 Running 0 5m37s 10.244.2.9 andes-cargo-cluster-worker <none> <none>
andes-cargo-status-api-65fcd6f6c8-m7qf8 1/1 Running 0 5m49s 10.244.2.8 andes-cargo-cluster-worker <none> <none>
andes-cargo-status-api-d6cd4d46b-79hdq 0/1 Running 0 20s 10.244.2.10 andes-cargo-cluster-worker <none> <none>
Este es exactamente el comportamiento que la lección 5 describió: STATUS: Running (el proceso sigue vivo), READY: 0/1 (la sonda de readiness está fallando), RESTARTS: 0 (nadie reinició nada). Confirma que el Service lo notó, sin que nadie se lo dijera explícitamente:
kubectl get endpoints status-api-service -n andes-cargo
Qué esperar (literal — exactamente las mismas tres IPs de antes; el Pod nuevo, 10.244.2.10, no aparece):
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
NAME ENDPOINTS AGE
status-api-service 10.244.1.7:8080,10.244.2.8:8080,10.244.2.9:8080 28m
El Pod con la sonda rota nunca llegó a la lista de Endpoints — el Service sigue enrutando tráfico únicamente hacia los tres Pods sanos, exactamente como prometió la lección 5. Confirma la causa exacta con kubectl describe:
kubectl describe pod andes-cargo-status-api-d6cd4d46b-79hdq -n andes-cargo
Qué esperar (la sección Events, literal — sustituye el nombre de Pod por el tuyo):
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 29s default-scheduler Successfully assigned andes-cargo/andes-cargo-status-api-d6cd4d46b-79hdq to andes-cargo-cluster-worker
Normal Pulled 28s kubelet spec.containers{andes-cargo-status-api}: Container image "andes-cargo-status-api:latest" already present on machine and can be accessed by the pod
Normal Created 28s kubelet spec.containers{andes-cargo-status-api}: Container created
Normal Started 28s kubelet spec.containers{andes-cargo-status-api}: Container started
Warning Unhealthy 3s (x5 over 23s) kubelet spec.containers{andes-cargo-status-api}: Readiness probe failed: HTTP probe failed with statuscode: 404
Readiness probe failed: HTTP probe failed with statuscode: 404 — el mensaje exacto de Kubernetes, sin ambigüedad sobre la causa. También confirma que, mientras tanto, el rollout está genuinamente estancado —Kubernetes está esperando, sin límite de tiempo, a que este Pod nuevo pase su readinessProbe antes de continuar reemplazando los Pods viejos:
kubectl rollout status deployment/andes-cargo-status-api -n andes-cargo --timeout=5s
Qué esperar (el comando agota su propio timeout de 5 segundos — el rollout en sí sigue detenido indefinidamente hasta que intervengas):
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
error: timed out waiting for the condition
Paso 3 — Corrige la ruta, y confirma la recuperación
kubectl patch deployment andes-cargo-status-api -n andes-cargo --type=json \
-p '[{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/health"}]'
kubectl rollout status deployment/andes-cargo-status-api -n andes-cargo --timeout=60s
Qué esperar:
deployment.apps/andes-cargo-status-api patched
deployment "andes-cargo-status-api" successfully rolled out
kubectl get pods -n andes-cargo -l app=andes-cargo-status-api -o wide
Qué esperar (algo notable: al revertir la ruta, la plantilla vuelve a coincidir exactamente con la del ReplicaSet original —mismo hash 65fcd6f6c8—, así que Kubernetes no crea Pods nuevos: simplemente termina el Pod con la sonda rota y confirma que tus tres Pods originales, que nunca dejaron de correr, siguen exactamente igual):
NAME READY STATUS RESTARTS AGE
andes-cargo-status-api-65fcd6f6c8-2bkht 1/1 Running 0 6m11s
andes-cargo-status-api-65fcd6f6c8-cnbjw 1/1 Running 0 6m5s
andes-cargo-status-api-65fcd6f6c8-m7qf8 1/1 Running 0 6m17s
Cero RESTARTS, en los tres — exactamente como predijo la lección 5: un fallo de readiness nunca reinicia nada, solo retira temporalmente del tráfico. Ese Pod estuvo fuera del Service durante todo el experimento, y ninguno de los tres Pods "de verdad" se enteró de que algo andaba mal.
Paso 4 — Induce un fallo de liveness
Ahora el segundo experimento: rompe la ruta de livenessProbe (dejando readinessProbe correcta) para ver la otra consecuencia.
kubectl patch deployment andes-cargo-status-api -n andes-cargo --type=json \
-p '[{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/httpGet/path","value":"/livez-check"}]'
Qué esperar:
deployment.apps/andes-cargo-status-api patched
Esta vez, como la sonda de readiness sí es correcta, el Pod nuevo sí se vuelve Ready y sí entra al Service casi de inmediato — el RollingUpdate avanza con normalidad, reemplazando los tres Pods viejos por tres Pods nuevos con la sonda de liveness rota. Observa la secuencia completa con kubectl get pods:
kubectl get pods -n andes-cargo -l app=andes-cargo-status-api -o wide
Qué esperar (unos segundos después del patch — el rollout ya avanzó, tres Pods nuevos 1/1 Ready, RESTARTS: 0 todavía, porque el livenessProbe recién empieza a evaluarse):
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
andes-cargo-status-api-7d56987475-7pxhd 1/1 Running 0 21s 10.244.2.12 andes-cargo-cluster-worker <none> <none>
andes-cargo-status-api-7d56987475-kn5tb 1/1 Running 0 27s 10.244.1.9 andes-cargo-cluster-worker2 <none> <none>
andes-cargo-status-api-7d56987475-z4f5p 1/1 Running 0 32s 10.244.2.11 andes-cargo-cluster-worker <none> <none>
Espera unos segundos más —initialDelaySeconds: 5 más failureThreshold: 3 con periodSeconds: 5 significan que el primer reinicio llega alrededor de los 20 segundos de vida del Pod— y repite el mismo comando:
kubectl get pods -n andes-cargo -l app=andes-cargo-status-api -o wide
Qué esperar (RESTARTS empieza a subir — cada Pod, uno por uno según su propio reloj, cruza el umbral de livenessProbe):
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
andes-cargo-status-api-7d56987475-7pxhd 1/1 Running 1 (11s ago) 62s 10.244.2.12 andes-cargo-cluster-worker <none> <none>
andes-cargo-status-api-7d56987475-kn5tb 1/1 Running 1 (17s ago) 68s 10.244.1.9 andes-cargo-cluster-worker2 <none> <none>
andes-cargo-status-api-7d56987475-z4f5p 1/1 Running 1 (23s ago) 73s 10.244.2.11 andes-cargo-cluster-worker <none> <none>
RESTARTS: 1 en los tres — el kubelet mató y volvió a arrancar cada contenedor, sin que el Pod en sí desapareciera (mismo nombre, misma IP, mismo AGE acumulado). Confirma la causa exacta con kubectl describe:
kubectl describe pod andes-cargo-status-api-7d56987475-z4f5p -n andes-cargo
Qué esperar (la sección Events, literal — sustituye el nombre de Pod por el tuyo):
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 79s default-scheduler Successfully assigned andes-cargo/andes-cargo-status-api-7d56987475-z4f5p to andes-cargo-cluster-worker
Normal Pulled 29s (x2 over 79s) kubelet spec.containers{andes-cargo-status-api}: Container image "andes-cargo-status-api:latest" already present on machine and can be accessed by the pod
Normal Created 29s (x2 over 79s) kubelet spec.containers{andes-cargo-status-api}: Container created
Normal Started 29s (x2 over 79s) kubelet spec.containers{andes-cargo-status-api}: Container started
Warning Unhealthy 4s (x6 over 69s) kubelet spec.containers{andes-cargo-status-api}: Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Killing 4s (x2 over 59s) kubelet spec.containers{andes-cargo-status-api}: Container andes-cargo-status-api failed liveness probe, will be restarted
Dos mensajes literales, sin ambigüedad: Liveness probe failed: HTTP probe failed with statuscode: 404, seguido de Container andes-cargo-status-api failed liveness probe, will be restarted. Fíjate en el (x2 over 59s) de Pulled/Created/Started: este Pod específico ya llevaba dos arranques del contenedor —el original, y uno de reemplazo tras el primer fallo de liveness— con la sonda todavía rota, camino a un segundo reinicio si el problema persistiera. Este es, exactamente, el mecanismo detrás de un CrashLoopBackOff: si la causa del fallo nunca se corrige, Kubernetes sigue reiniciando, con un intervalo de espera que crece entre intento e intento.
Paso 5 — Corrige la ruta, y confirma la recuperación final
kubectl patch deployment andes-cargo-status-api -n andes-cargo --type=json \
-p '[{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/httpGet/path","value":"/health"}]'
kubectl rollout status deployment/andes-cargo-status-api -n andes-cargo --timeout=90s
Qué esperar:
deployment.apps/andes-cargo-status-api patched
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "andes-cargo-status-api" rollout to finish: 1 old replicas are pending termination...
deployment "andes-cargo-status-api" successfully rolled out
kubectl get deployment andes-cargo-status-api -n andes-cargo
kubectl get endpoints status-api-service -n andes-cargo
Qué esperar (de vuelta a 3/3 sano, con tres Endpoints — nombres de Pod e IPs nuevos frente a los del inicio de esta lección, porque esta vez sí hubo un RollingUpdate completo, no una simple terminación como en el Paso 3):
NAME READY UP-TO-DATE AVAILABLE AGE
andes-cargo-status-api 3/3 3 3 32m
Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
NAME ENDPOINTS AGE
status-api-service 10.244.1.10:8080,10.244.2.13:8080,10.244.2.14:8080 31m
El contraste completo, en una tabla
Fallo de readiness (Paso 2) | Fallo de liveness (Paso 4) | |
|---|---|---|
STATUS | Running, sin cambio | Running, sin cambio |
READY | 0/1 | 1/1 (el reinicio es tan rápido que rara vez lo capturas en 0/1) |
RESTARTS | 0, siempre | Sube con cada ciclo de fallo |
Endpoints del Service | El Pod sale, sin reiniciarse | El Pod nunca sale (mientras readiness siga pasando) |
Mensaje de kubectl describe | Readiness probe failed | Liveness probe failed + Killing... will be restarted |
| Consecuencia sobre tráfico existente | Ninguna — el Service ya lo excluyó | Ninguna, mientras el Pod se recupere entre reinicios |
Errores comunes
Dejar una sonda rota corriendo demasiado tiempo, y terminar en un CrashLoopBackOff real de difícil salida (de flujo, el riesgo más directo de este experimento). Qué pasa: alguien repite el Paso 4 sin revertir la sonda de inmediato después de confirmar el primer reinicio, y dos o tres ciclos de fallo después, el intervalo de espera entre reinicios (backoff) ya es de varios minutos, haciendo que la corrección tarde en reflejarse. Por qué pasa: Kubernetes usa un backoff exponencial para reinicios repetidos —cada fallo espera más que el anterior— precisamente para no saturar el sistema con reinicios constantes, pero eso significa que revertir tarde alarga la recuperación. Cómo detectarlo: si RESTARTS ya muestra 3 o más antes de que hayas corregido la ruta. Cómo corregirlo: en cuanto confirmes el mensaje Liveness probe failed en los Events (como en el Paso 4 de esta lección), revierte de inmediato — no hace falta dejar que el ciclo se repita varias veces para confirmar el mecanismo.
Confundir el Pod "atascado en 0/1" del Paso 2 con un Pod fallado o en error (de expectativa). Qué pasa: alguien ve READY: 0/1 y asume que algo se rompió gravemente, cuando en realidad el contenedor está perfectamente sano —solo que su sonda de readiness está configurada para preguntar algo que nunca va a responder que sí. Cómo detectarlo: STATUS sigue en Running, RESTARTS sigue en 0 — ninguna de las dos señales de un problema grave está presente. Cómo corregirlo: READY: 0/1 con STATUS: Running y RESTARTS: 0 es, específicamente, la firma de un fallo de readiness — revisa la sonda, no el contenedor.
Olvidar que strategy.rollingUpdate con maxUnavailable: 0 es lo que protegió a los Pods originales durante todo este experimento (conceptual). Qué pasa: alguien repite este mismo experimento en un Deployment sin esa configuración explícita (usando el valor por defecto, maxUnavailable: 25%) y se sorprende al ver que, durante el fallo de readiness, la capacidad disponible del Service sí bajó momentáneamente. Cómo detectarlo: compara maxSurge/maxUnavailable de tu deployment.yaml contra el valor por defecto de Kubernetes. Cómo corregirlo: maxUnavailable: 0 (usado en esta lección) le exige a Kubernetes mantener el 100% de las réplicas existentes disponibles durante cualquier despliegue, incluso uno que termina fallando —es una decisión deliberada de esta guía para que el experimento del Paso 2 fuera seguro de repetir sin arriesgar disponibilidad real.
Ejercicios
Ejercicio 1 — Reconstruye el contraste sin la tabla. Sin volver a la tabla de esta lección, describe, en tus propias palabras, la diferencia completa entre lo que viste en el Paso 2 y lo que viste en el Paso 4.
Ver solución
En el Paso 2 (fallo de readiness), el Pod nuevo nunca llegó a los Endpoints del Service — quedó Running con READY: 0/1, RESTARTS: 0, sin ninguna consecuencia para los tres Pods sanos que ya atendían tráfico. En el Paso 4 (fallo de liveness), como la sonda de readiness sí pasaba, los Pods nuevos sí entraron al Service con normalidad — pero después de varios fallos consecutivos de liveness, el kubelet los reinició, uno por uno, incrementando su contador de RESTARTS sin que el Pod cambiara de nombre ni de IP.
Ejercicio 2 — Explica por qué el Paso 3 no creó Pods nuevos, pero el Paso 5 sí. Ambos pasos revierten una sonda rota a /health. Explica, en dos o tres frases, por qué el Paso 3 solo terminó un Pod existente mientras que el Paso 5 disparó un RollingUpdate completo con Pods nuevos.
Ver solución
En el Paso 3, al revertir readinessProbe a /health, la plantilla completa del Deployment volvió a coincidir exactamente con el hash del ReplicaSet original (el de los tres Pods que nunca se tocaron durante el experimento) — Kubernetes reconoció que ya existían suficientes réplicas de esa plantilla exacta, así que solo terminó el Pod sobrante con la sonda rota. En el Paso 5, en cambio, los tres Pods "sanos" en ese momento ya pertenecían a un ReplicaSet nuevo (creado durante el fallo de liveness, con la sonda rota en su plantilla) — revertir la sonda creó un hash de plantilla distinto al de esos tres Pods, así que Kubernetes tuvo que reemplazarlos, uno por uno, con un RollingUpdate completo.
Ejercicio 3 — Diseña una probe para un tercer escenario. andes-cargo-status-api en un futuro módulo va a depender de una conexión persistente a una base de datos que tarda hasta 10 segundos en establecerse al arrancar. ¿Qué sonda usarías para evitar que Kubernetes mate el contenedor durante esos 10 segundos iniciales, y con qué parámetro clave?
Ver solución
Un startupProbe con failureThreshold × periodSeconds mayor a 10 segundos —por ejemplo, periodSeconds: 2 con failureThreshold: 8 (16 segundos de margen)—, apuntando al mismo /health o a un endpoint específico que confirme la conexión establecida. Mientras el startupProbe no tenga éxito, ni readinessProbe ni livenessProbe se evalúan — evitando exactamente el escenario descrito: un livenessProbe demasiado impaciente matando un contenedor que solo está tardando en establecer su conexión inicial, no roto.
Resumen y siguiente paso
Esta lección agregó las tres sondas de la lección 5 al Deployment real, y confirmó con evidencia real —no solo en teoría— las dos consecuencias centrales: un fallo de readiness induce READY: 0/1 con RESTARTS: 0, sacando al Pod de los Endpoints del Service sin ninguna interrupción para el resto; un fallo de liveness induce reinicios reales del contenedor, confirmados con RESTARTS incrementando y los mensajes exactos Liveness probe failed/Killing... will be restarted en los Events. Ambos experimentos se hicieron de forma segura, protegiendo la disponibilidad real gracias a maxUnavailable: 0, y se revirtieron por completo antes de seguir.
Antes de avanzar deberías poder: distinguir, con solo kubectl get pods, si un Pod está fallando readiness o liveness; leer los Events de kubectl describe pod para confirmar la causa exacta de cualquiera de los dos; y explicar por qué proteger maxUnavailable: 0 durante un experimento de sondas es una práctica segura y reversible.
Siguiente lección: HorizontalPodAutoscaler, escalar por métricas, no por corazonada. Con configuración y salud resueltas, el módulo cierra con la tercera pregunta de la lección 1: ¿qué pasa si el tráfico se multiplica de golpe?
Recursos
- Kubernetes — Configure Liveness, Readiness and Startup Probes — la misma referencia de la lección 5, ahora confirmada con evidencia real.
- Kubernetes — Deployments: Rolling Update Deployment — referencia oficial de
maxSurge/maxUnavailable, el mecanismo que hizo seguros los experimentos de esta lección. - Kubernetes — Debug Running Pods — referencia oficial de
kubectl describe pody la lectura deEvents, la técnica central de diagnóstico de esta lección.