4.2 · Fiabilizar: healthcheck y políticas de reinicio

Nivel 4 · Registros, fiabilidad y CI

4.2Fiabilizar: healthcheck y políticas de reinicio

Objetivo: Hacer un servicio capaz de reiniciarse solo y de señalar su estado real.
Tiempo estimado: 12 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • restart resucita, healthcheck prueba : la política de reinicio relanza el contenedor tras fallo o reinicio ; la prueba de salud periódica dice si el servicio está realmente listo (no solo iniciado).
  • depends_on ordena, condition: service_healthy espera lo realmente listo : sin condición, el orden de arranque es solo una esperanza — con un healthcheck en la base, la API solo arranca sobre probado sano.
  • Reflejo de Idir : unless-stopped por defecto (respeta las paradas voluntarias), y Up no es healthy : un servicio Up pero unhealthy es un enfermo por curar, no un servicio que funciona.

Mini-caso hilado — Idir acaba con los fallos del lunes por la mañana

Idir, devops junior en Argel, se despierta con una alerta : tras un corte eléctrico, la API está iniciada pero la base no estaba lista — fallos en cascada. Añade restart: unless-stopped a cada servicio duradero, un healthcheck pg_isready en la base, y hace depender la API de service_healthy. Luego mata la base para verificar : relanzamiento automático y espera probada. Segundo hito del hilo : la stack se reinicia sola y solo enruta hacia lo probado sano.

Continuación del caso 4.1 — la imagen publicada por Idir corre ahora de forma autónoma.

1. restart : la política de resurrección

restart: unless-stopped relanza el contenedor tras un fallo o un reinicio de máquina, salvo parada voluntaria — el buen defecto para un servicio duradero. always relanza incluso tras un stop manual (reservado a servicios críticos), on-failure solo relanza en caso de error. Sin política, como antes de la corrección de Idir, un fallo nocturno espera hasta la mañana.

Elegir según la intención : duradero (unless-stopped), crítico que nunca debe pararse (always), tarea que solo debe reanudarse en fallo (on-failure). Y se evita always en todas partes : reinicia incluso sus paradas voluntarias.

2. healthcheck : « listo » vale más que « iniciado »

depends_on ordena, healthcheck prueba : un comando probado periódicamente (pg_isready para Postgres, una petición HTTP para una API) pasa el servicio a healthy. Entonces se puede esperar lo realmente listo (condition: service_healthy) en lugar de esperar que la base haya terminado de arrancar.

La prueba debe apuntar al servicio real (una petición, no la simple presencia del proceso) : eso es lo que hace desaparecer los fallos de arranque « base no lista » de Idir.

3. Tres estados, tres reacciones

starting (se espera), healthy (se enruta), unhealthy (se alerta, ya no se envía tráfico). docker compose ps muestra el estado : un servicio Up pero unhealthy es un enfermo por curar (logs, diagnóstico), no un servicio que funciona.

Ajustar la frecuencia con medida : bastante a menudo para detectar (10 a 30 segundos), con reintentos repetidos para evitar falsos positivos. Una prueba demasiado agresiva se pasa señalando ; demasiado rara, pierde los fallos.

Error frecuente de interpretación: « depends_on basta para ordenar el arranque, y always en todas partes es más seguro ». No. Sin condición service_healthy, depends_on solo ordena el inicio sin esperar que la base esté lista — vuelven los fallos « base no lista » ; y always en todas partes reinicia incluso sus paradas voluntarias de mantenimiento. unless-stopped por defecto, healthcheck que prueba, condición que espera : ese trío es lo que fiabiliza.
Hacer un servicio autónomo Relanzamiento auto, salud probada, tráfico hacia lo sano Política restart Relanzatras fallo o reinicioPrueba healthcheck Pruebalo realmente listoDependencia condicional Esperaservice_healthyLectura del estado Upno es healthy
Relanzamiento auto, salud probada, tráfico hacia lo sano
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Idir añade restart: unless-stopped a cada servicio duradero para sobrevivir a fallos y reinicios. 2) Añade un healthcheck pg_isready en la base que prueba lo realmente listo. 3) Hace depender la API de service_healthy en lugar de un simple orden de arranque. 4) Lee docker compose ps : Up pero unhealthy significa diagnosticar, no enrutar. Lección : restart resucita, healthcheck prueba, la condición espera lo realmente listo.

¿Lo sabías?

Un contenedor puede mostrar Up desde hace horas mientras su aplicación ya no responde a nadie — el proceso vive, el servicio está muerto.
Verdadero : Up describe el proceso, healthy describe el servicio. De ahí el healthcheck.

Up es el pulso ; healthy es la forma.

🔎 Ejemplo concreto — 🔎 Ejemplo concreto — Postgres que prueba su salud

La stack de Idir : la API solo arranca sobre base probada lista.

services:
  bdd:
    image: postgres:16.4
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 10s
      retries: 5
  api:
    build: ./api
    depends_on:
      bdd:
        condition: service_healthy

Lectura : la API solo arranca sobre base probada lista.

Lección : los fallos de arranque « base no lista » desaparecen.

Vocabulario de la sección

restart
Política de relanzamiento automático del contenedor : no, on-failure, always, unless-stopped.

Ejemplo sencillo: Idir pone unless-stopped : relanza tras fallo o reinicio, pero respeta su stop manual.

Lo que no es: un reinicio manual a las 3 de la mañana tras cada fallo.

Reflejo: servicio duradero : declarar una política restart.

healthcheck
Prueba periódica que prueba la SALUD REAL del servicio (petición, no simple proceso).

Ejemplo sencillo: pg_isready prueba que la base de Idir acepta realmente las conexiones.

Lo que no es: un simple orden de arranque sin verificación.

Reflejo: dependencia crítica : probar el servicio real.

healthy / unhealthy
Estado sano o enfermo según la última prueba de salud — independiente de que el proceso corra.

Ejemplo sencillo: La base de Idir está Up pero unhealthy : diagnostica en lugar de enrutar.

Lo que no es: un simple marcha o paro.

Reflejo: Up + unhealthy : curar, no enrutar.

condition: service_healthy
En depends_on : esperar que la dependencia esté probada sana antes de arrancar.

Ejemplo sencillo: La API de Idir espera la base healthy en lugar de esperar.

Lo que no es: un orden de inicio sin garantía de disponibilidad.

Reflejo: arranque ordenado : exigir la condición, no solo el orden.

En la práctica — En práctica — Hacer su stack autónoma

  1. Añada restart: unless-stopped a cada servicio duradero.
  2. Añada un healthcheck a la base (pg_isready).
  3. Haga depender la API de service_healthy.
  4. Mate la base (kill) : observe relanzamiento + espera probada.
Su stack se reinicia sola y solo enruta hacia lo probado sano.

Guion listo para decir — explicar la fiabilización al equipo (30 s)

« Soy Idir : cada servicio duradero se reinicia solo tras un fallo, la base prueba que está lista con una prueba real, y la API espera esa prueba antes de arrancar. Se acabaron los despertares tras un corte : la stack se levanta sola. »

Para decir en revisión : muestre la prueba kill de la base delante del equipo.

Modelo copiar-pegar — base probada + API que espera (Compose)

services:
  bdd:
    image: postgres:16.4
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 10s
      timeout: 5s
      retries: 5
  api:
    build: ./api
    restart: unless-stopped
    depends_on:
      bdd:
        condition: service_healthy

API web por probar en HTTP

Como Idir pero con una prueba de petición web en la página de inicio : el servicio está healthy cuando responde realmente.

Servicio crítico 24/7

restart: always asumido y documentado : incluso un stop manual relanza — reservar a los casos realmente críticos.

Tarea puntual

restart: on-failure : solo se relanza en caso de error, no tras un éxito normal.

Falsa sensación de seguridad

depends_on sin condición + prueba que apunta al contenedor equivocado : corregir hacia service_healthy y prueba real.

✓ Buenas prácticas

  • unless-stopped por defecto en duradero.
  • Probar el servicio real (petición, no el PID).
  • Leer el estado health en compose ps.

✗ Errores frecuentes

  • always en todas partes (reinicia incluso sus stops).
  • depends_on sin condición (falsa sensación).
  • Healthcheck que prueba el contenedor equivocado.

Puntos clave

  • restart resucita, healthcheck prueba.
  • depends_on + condición = orden real.
  • Up no es healthy.
  • unless-stopped : el buen defecto.

Reto 48h — aplique mañana

En su stack real : añada unless-stopped + healthcheck + condición, mate la base y observe relanzamiento y espera probada.

Lista de salida de la sección
  • Sé declarar una política restart adaptada.
  • Sé escribir un healthcheck que prueba lo realmente listo.
  • Sé hacer esperar service_healthy y leer el estado.
Autoevaluación 1-5 : ¿mi stack sobreviviría a un reinicio nocturno sin mí?¿mis dependencias esperan lo realmente listo o un simple orden?

Preguntas frecuentes

¿Healthcheck o simple reintento en la app?

Ambos : los reintentos hacen la app robusta en todas partes, el healthcheck hace la stack observable y planificable. Son aliados, no competidores.

¿Qué frecuencia de prueba?

Bastante a menudo para detectar (10 a 30 segundos), con reintentos repetidos para evitar falsos positivos. Una prueba demasiado agresiva señala sin parar ; demasiado rara, pierde los fallos.

Comprueba tu comprensión

Un servicio está « Up (unhealthy) ». ¿Qué hay que entender?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 4Preguntas inéditas y más difíciles para validar tus conocimientos