Módulo 3: Configuration Secrets Health And Autoscaling

5. `liveness`, `readiness` y `startup probes`

Descripción

Hoy, andes-cargo-status-api tiene tres réplicas con STATUS: Running — pero "el proceso arrancó" y "el proceso está en condiciones de atender una solicitud real" son afirmaciones distintas, y Kubernetes, hasta este punto de la guía, no tiene ninguna forma de distinguirlas. Si uno de los tres Pods se colgara ahora mismo —sin crashear, solo dejando de responder—, kubectl get pods seguiría mostrando Running, y el Service seguiría enviándole tráfico indefinidamente. Esta lección resuelve exactamente ese punto ciego con tres mecanismos de verificación de salud, cada uno respondiendo una pregunta distinta.

Conexión con el módulo

Esta es la segunda de las tres piezas que la lección 1 prometió. La lección 6 agrega probes reales al Deployment y provoca, a propósito, un fallo de cada tipo —viendo con evidencia real qué hace Kubernetes en cada caso.


El problema exacto: Running no significa Sano

STATUS: Running, la columna que ya conoces de cada kubectl get pods de esta guía, responde una sola pregunta: ¿el contenedor tiene un proceso principal vivo? Esa pregunta se responde a nivel del sistema operativo —el kubelet verifica que el proceso con PID 1 dentro del contenedor no haya terminado—, sin ninguna noción de qué hace ese proceso ni si lo hace correctamente. Un servidor Flask que entró en un bucle infinito sin responder a ninguna solicitud, o que perdió su conexión a una base de datos crítica, sigue teniendo un proceso vivo — sigue siendo Running, indefinidamente, mientras nadie le pregunte nada más específico.

Kubernetes ofrece tres mecanismos para hacer preguntas más específicas, cada uno con una consecuencia distinta cuando la respuesta es "no":

SondaPregunta que haceQué hace Kubernetes si falla
startupProbe¿Ya terminó de arrancar esta aplicación?Nada más se ejecuta (ni liveness ni readiness) hasta que esta sonda tenga éxito, o hasta agotar su propio failureThreshold (en cuyo caso, reinicia el contenedor)
readinessProbe¿Está esta réplica lista para recibir tráfico ahora mismo?Saca al Pod de la lista de Endpoints del Service — el contenedor sigue corriendo, sin reiniciarse, solo deja de recibir tráfico nuevo
livenessProbe¿Sigue vivo este proceso, o está tan roto que hay que reemplazarlo?Reinicia el contenedor (el mismo mecanismo que dispara un CrashLoopBackOff si el problema persiste)

Analogía: el chequeo médico, tres preguntas distintas

Piensa en cada Pod como un empleado que se presenta a trabajar. Un startupProbe es la pregunta que se le hace el primer día: "¿ya terminaste de instalarte en tu puesto, tienes tu computadora encendida y tus credenciales funcionando?" — hasta que la respuesta sea sí, nadie más le pregunta nada, ni se espera que atienda a ningún cliente todavía. Un readinessProbe es la pregunta que se le hace cada pocos minutos durante el día: "¿puedes atender clientes ahora mismo?" — si la respuesta es no (está en una llamada larga, en el baño, en una reunión), simplemente se desvían los clientes nuevos hacia otro empleado, sin que nadie le diga que está despedido; en cuanto vuelve a responder que sí, vuelve a recibir clientes con total normalidad. Un livenessProbe es una pregunta mucho más grave: "¿sigues siendo tú, o hay que llamar a un reemplazo porque algo salió profundamente mal?" — si la respuesta es no, de forma sostenida, la organización no espera: reemplaza a esa persona por una nueva, con la esperanza de que la nueva sí funcione.


Anatomía de una probe

Las tres sondas comparten la misma estructura de campos —cambia el nombre (startupProbe/readinessProbe/livenessProbe), pero los parámetros son idénticos:

readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 2
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 1
  successThreshold: 1
  • El mecanismo de verificación (httpGet aquí — Kubernetes también ofrece tcpSocket, para confirmar solo que un puerto acepta conexiones, y exec, para correr un comando dentro del contenedor y evaluar su código de salida). Esta guía usa httpGet contra /health, el mismo endpoint que app.py ya expone desde aws-serverless-and-containers-guide, Módulo 6 — un endpoint que responde 200 sin depender de ningún dato externo, exactamente el tipo de chequeo liviano que una probe necesita.
  • initialDelaySeconds — cuánto espera el kubelet después de que el contenedor arranca antes de hacer la primera verificación.
  • periodSeconds — cada cuántos segundos repite la verificación.
  • timeoutSeconds — cuánto espera una respuesta antes de contar ese intento como fallido.
  • failureThreshold — cuántos fallos consecutivos hacen falta para considerar la sonda "fallida" (y disparar la consecuencia de la tabla anterior).
  • successThreshold — cuántos éxitos consecutivos hacen falta para volver a considerarla "exitosa" después de haber fallado (por defecto 1 para readiness/startup; liveness siempre usa 1, por diseño de Kubernetes).

Por qué confundir readiness con liveness es el error más común de esta capa

La confusión más frecuente en clústeres reales —y la razón por la que esta lección le dedica una sección completa antes de la práctica— es usar la misma sonda con la misma consecuencia para los dos casos, sin distinguir "temporalmente ocupado" de "roto de verdad". Un ejemplo real y común: una aplicación que, bajo carga alta, tarda unos segundos extra en responder. Si esa lentitud se mide con un livenessProbe demasiado estricto (timeoutSeconds bajo, failureThreshold bajo), Kubernetes va a reiniciar un proceso que no estaba roto — solo estaba ocupado—, empeorando el problema: menos réplicas disponibles justo cuando más se necesitan, cada reinicio agregando su propio tiempo de arranque a la presión ya existente. Ese mismo escenario, medido con un readinessProbe, simplemente saca temporalmente al Pod ocupado de la lista de tráfico —sin reiniciar nada—, dejando que se recupere solo y vuelva a entrar en cuanto pueda responder de nuevo.

La regla práctica que esta guía sigue: readinessProbe debe ser más sensible (falla más rápido) que livenessProbe (falla más lento, con más margen). Sacar un Pod del Service temporalmente es una operación barata y reversible; reiniciar un contenedor es una operación cara y, si la causa no se resuelve sola, puede entrar en un ciclo de reinicios (CrashLoopBackOff) que empeora la disponibilidad en vez de mejorarla. La lección 6 usa exactamente esta asimetría: readinessProbe con failureThreshold: 1 (falla al primer intento fallido), livenessProbe con failureThreshold: 3 (necesita tres fallos consecutivos antes de reiniciar).

              LAS TRES SONDAS, EN EL CICLO DE VIDA DE UN CONTENEDOR

  Contenedor arranca
        │
        ▼
  ┌─────────────────┐   falla repetido    ┌──────────────────┐
  │  startupProbe    │ ───────────────────▶│  reinicia el      │
  │  "¿ya arrancó?"  │                      │  contenedor        │
  └────────┬─────────┘                      └──────────────────┘
           │ éxito
           ▼
  ┌──────────────────────┐        ┌──────────────────────┐
  │  readinessProbe        │        │  livenessProbe          │
  │  "¿listo AHORA?"       │        │  "¿sigue vivo de verdad?"│
  │  corre en paralelo      │        │  corre en paralelo        │
  │  con liveness, siempre  │        │  con readiness, siempre    │
  └──────────┬─────────────┘        └───────────┬──────────────┘
             │ falla                              │ falla repetido
             ▼                                    ▼
   sale de Endpoints del             el kubelet reinicia
   Service — SIN reiniciar           el contenedor
   (Errores comunes, lección 6)      (Errores comunes, lección 6)

Errores comunes

Usar el mismo endpoint y los mismos umbrales para readiness y liveness, sin pensar en la asimetría (conceptual, el más importante de esta lección). Qué pasa: alguien copia la misma configuración exacta de readinessProbe a livenessProbe, razonando que "si el endpoint está bien para uno, está bien para el otro". Por qué pasa: técnicamente funciona, y no produce ningún error inmediato — el problema aparece solo bajo condiciones reales de carga o lentitud transitoria, cuando ambas sondas fallan al mismo tiempo y Kubernetes reinicia Pods que solo estaban ocupados, no rotos. Cómo detectarlo: si tu livenessProbe tiene failureThreshold igual o menor que tu readinessProbe. Cómo corregirlo: la regla de esta lección — readiness sensible y barato de fallar (sale del tráfico, se recupera solo), liveness con más margen y más caro de fallar (reinicia un proceso). La lección 6 aplica esta asimetría con evidencia real.

Apuntar una probe a un endpoint que depende de servicios externos (de diseño, un error sutil). Qué pasa: alguien configura livenessProbe contra un endpoint que, como /shipments/<id> en este punto de la guía, depende de una base de datos externa — y en cuanto esa base de datos externa tiene un problema pasajero, Kubernetes empieza a reiniciar contenedores sanos que solo dependen de un tercero caído, sin resolver nada (reiniciar el proceso no arregla la base de datos). Cómo detectarlo: si tu endpoint de probe hace alguna llamada de red hacia afuera del propio proceso. Cómo corregirlo: un endpoint de probe debe verificar solo la salud del propio proceso —exactamente el diseño de /health en app.py, que responde 200 sin ninguna dependencia externa—, nunca la salud de un sistema del que depende indirectamente.

Olvidar que las tres sondas corren de forma continua, no solo una vez (de expectativa). Qué pasa: alguien asume que, una vez que un Pod pasa su readinessProbe la primera vez, ya "aprobó" para siempre y la sonda deja de correr. Por qué pasa: el nombre "sonda de arranque" (startupProbe) sí funciona así —una vez, hasta el primer éxito—, y es fácil generalizar esa idea a las otras dos. Cómo detectarlo: si te sorprende ver un Pod que llevaba horas Ready salir de pronto de la lista de Endpoints. Cómo corregirlo: readinessProbe y livenessProbe corren cada periodSeconds, durante toda la vida del Pod, sin excepción — un Pod que estuvo sano por horas puede fallar su readinessProbe en cualquier momento si deja de responder correctamente, exactamente el escenario que la lección 6 va a inducir a propósito.


Ejercicios

Ejercicio 1 — Completa la tabla de las tres sondas de memoria. Sin volver a la sección correspondiente, para cada una de las tres sondas, escribe la pregunta que hace y la consecuencia exacta de que falle.

Ver solución
SondaPreguntaConsecuencia del fallo
startupProbe¿Ya terminó de arrancar?Bloquea readiness/liveness hasta el éxito, o reinicia si agota su propio umbral
readinessProbe¿Está lista para tráfico ahora?Sale de Endpoints del Service, sin reiniciar
livenessProbe¿Sigue viva de verdad?El kubelet reinicia el contenedor

Ejercicio 2 — Diagnostica un diseño de probes mal hecho. Un equipo configura livenessProbe con failureThreshold: 1 y timeoutSeconds: 1 contra un endpoint que hace una consulta lenta a una base de datos. Explica, en dos o tres frases, qué va a pasar bajo carga alta, y por qué es un error de diseño.

Ver solución

Bajo carga alta, la consulta a la base de datos probablemente tarde más de 1 segundo en responder al menos una vez — con failureThreshold: 1, un solo fallo (que puede ser solo lentitud pasajera, no un proceso roto) es suficiente para que Kubernetes reinicie el contenedor. El error de diseño es doble: usar un endpoint que depende de un sistema externo lento para liveness (en vez de un /health liviano), y darle un margen de fallo casi nulo (failureThreshold: 1) a una sonda cuya consecuencia es la más cara de las tres (reiniciar un proceso). El resultado real es reiniciar procesos sanos justo en el peor momento —bajo carga alta—, reduciendo la capacidad disponible cuando más se necesita.

Ejercicio 3 — Explica la analogía del chequeo médico sin usar "readiness" ni "liveness". En dos o tres frases, sin nombrar ningún término técnico de Kubernetes, explica la diferencia entre las dos preguntas de salud continua de esta lección, usando la analogía del empleado.

Ver solución

Una respuesta razonable: "Una pregunta se hace todo el día, cada pocos minutos: '¿puedes atender un cliente ahora mismo?' — si la respuesta es no por un momento (está en el baño, en una llamada), simplemente se desvían los clientes hacia otro compañero, sin ninguna consecuencia grave, y en cuanto vuelve a estar disponible retoma su trabajo con normalidad. La otra pregunta es mucho más seria y se responde con mucho más margen antes de actuar: '¿sigue siendo la misma persona, o hay que reemplazarla por completo?' — esa decisión no se toma a la primera señal de duda, solo después de varias confirmaciones de que algo está genuinamente mal."


Resumen y siguiente paso

Esta lección resolvió el punto ciego que dejó el Deployment de los módulos anteriores: STATUS: Running solo confirma que un proceso está vivo, no que esté en condiciones de atender tráfico. Las tres sondas —startupProbe, readinessProbe, livenessProbe— responden preguntas distintas, con consecuencias distintas: la primera bloquea el resto hasta que arranca; la segunda saca al Pod del Service sin reiniciarlo; la tercera reinicia el contenedor. La regla dura de esta lección —readiness sensible y barato de fallar, liveness con más margen y caro de fallar— existe precisamente para evitar el error más común de esta capa: confundir "temporalmente ocupado" con "roto de verdad".

Antes de avanzar deberías poder: explicar la diferencia exacta entre las tres sondas, sin confundir sus consecuencias; justificar por qué readiness debería tener un failureThreshold más bajo que liveness; y explicar por qué una probe nunca debería depender de un sistema externo.

Siguiente lección: manos a la obra, probes reales sobre status-api-service. Ahí agregas las tres sondas al Deployment real, y provocas —a propósito, de forma controlada— un fallo de readiness y un fallo de liveness, viendo la diferencia exacta con tus propios ojos.

Recursos

  1. Kubernetes — Configure Liveness, Readiness and Startup Probes — la guía oficial completa, con ejemplos de los tres mecanismos de verificación (httpGet, tcpSocket, exec).
  2. Kubernetes — Pod Lifecycle: Container probes — referencia oficial del ciclo de vida completo y la interacción entre las tres sondas.
  3. aws-serverless-and-containers-guide (NIEVA), Módulo 6, lección 5 — el endpoint /health, sin ningún cambio, que esta guía reutiliza como el chequeo de las tres sondas.