Aplicación congelada? Cómo configurar liveness y readiness probes
Aprende a configurar sondas de salud en contenedores para evitar reinicios innecesarios y caídas de tráfico en tu aplicación.
Resumen
- Las verificaciones de salud evitan que el orquestador envíe tráfico a instancias inestables
- Ajustar intervalos y umbrales de fallo previene bucles de reinicio en cascada
- Liveness maneja bloqueos internos mientras readiness gestiona el flujo activo de tráfico de red
- Monitorear SLOs ayuda a calibrar tiempos de respuesta aceptables para las sondas
- Herramientas como Prometheus complementan las sondas nativas para mejorar la observabilidad
Por qué se reinicia tu aplicación de la nada?
Cuando ejecutamos aplicaciones en sistemas de orquestación de contenedores, el orquestador necesita saber si el software realmente está vivo o si solo está ocupando espacio en la memoria. En la práctica, esto significa que un proceso puede estar ejecutándose y, al mismo tiempo, ser incapaz de responder a cualquier solicitud debido a un bloqueo interno en la base de datos. Para evitar que los usuarios se enfrenten a pantallas de error eternas, utilizamos mecanismos de inspección conocidos como verificaciones de salud. Antes de llevar cualquier sistema a producción, garantizar la resiliencia exige entender exactamente cómo el orquestador interactúa con tu aplicación mediante sondas automatizadas.
Sin una configuración adecuada, cualquier variación momentánea en la red o pico de carga puede hacer que el sistema mate el contenedor de forma agresiva. Esto genera un ciclo vicioso de reinicios innecesarios que consume valiosos recursos de CPU y memoria. Además, cuando nuevos contenedores arrancan, a menudo reciben tráfico en vivo antes de que sus cachés estén poblados, lo que genera una latencia visible. Para mitigar estos escenarios, la ingeniería de confiabilidad se basa en dos conceptos fundamentales que trabajan juntos pero con propósitos totalmente diferentes: las sondas de vivencia y las sondas de preparación.
Entendiendo la diferencia entre liveness y readiness
La sonda de vivencia, o liveness probe, tiene una misión muy específica: descubrir si el contenedor se ha bloqueado por completo y necesita ser reiniciado desde cero. En la práctica, si esta verificación falla repetidamente, el orquestador destruye el proceso actual y crea un contenedor totalmente nuevo para ocupar su lugar. Un error clásico es configurar esta verificación apuntando a una ruta pesada que depende de servicios externos, como APIs de terceros. Si la API externa se cae, toda tu aplicación comienza a reiniciarse innecesariamente, empeorando el problema original que estaba fuera de tu control.
Por otro lado, la sonda de preparación, o readiness probe, decide si el contenedor está listo para recibir tráfico de red de los usuarios. Piense en esto como un cajero que enciende su letrero de 'abierto' solo después de iniciar el sistema y contar el cambio en el cajero. Si la preparación falla, el contenedor no se reinicia; simplemente se aísla temporalmente del balanceador de carga hasta que responda con éxito nuevamente. Esta separación garantiza que las solicitudes reales de los usuarios nunca caigan en una instancia que acaba de arrancar y todavía está calentando conexiones o compilando plantillas internas.
Cómo configurar liveness y readiness en la práctica
Configurar estas verificaciones requiere atención minuciosa a los tiempos de espera y umbrales de tolerancia a fallos. Si defines un intervalo demasiado corto entre comprobaciones, cualquier pico momentáneo de CPU se interpretará como un fallo catastrófico. En la práctica, tu archivo de configuración debe equilibrar el tiempo que tarda la aplicación en arrancar con la frecuencia de las inspecciones de rutina. A continuación, presentamos un ejemplo práctico de un manifiesto en YAML aplicando estas directrices en un entorno de microservicios:
apiVersion: v1
kind: Pod
metadata:
name: mi-aplicacion
spec:
containers:
- name: app
image: mi-imagen:v1
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5En el ejemplo anterior, la sonda de vivencia espera treinta segundos antes de probar la ruta de salud, dando tiempo suficiente para que el binario cargue en la memoria. Mientras tanto, la sonda de preparación comienza a verificar la ruta a los cinco segundos, permitiendo que el tráfico fluya tan pronto como los componentes esenciales estén activos. Esta sincronización fina evita reinicios prematuros y asegura una transición suave durante las actualizaciones de versión. Si necesitas escalar infraestructuras complejas, vale la pena revisar estrategias complementarias como las analizadas en cómo escalar runners de GitLab en Kubernetes para mantener la estabilidad operativa.
Uno de los errores más comunes cometidos por los equipos de ingeniería es utilizar la misma ruta de código para ambos tipos de verificación. Cuando apuntas tanto la vivencia como la preparación a un único extremo que valida la base de datos, el sistema se vuelve vulnerable a fallos sistémicos en cascada. Si la base de datos sufre una ralentización momentánea, todas las instancias de la aplicación fallan en su vivencia al mismo tiempo, lo que provoca que el orquestador las mate simultáneamente. Esto genera un apagón total en lugar de una degradación elegante del servicio, sobrecargando aún más la infraestructura con tormentas de reconexión.
Para evitar este comportamiento indeseado, crea rutas aisladas y ligeras en tu código para cada tipo de verificación. La ruta de vivencia solo debe comprobar si el hilo principal responde y asegurar que no existan bloqueos graves en la memoria interna. Por el contrario, la ruta de preparación puede realizar validaciones más profundas, como verificar si las tablas principales de la base de datos responden o si el caché local está poblado. Además, para mantener una visión clara de la salud del sistema en producción, puedes correlacionar estas métricas con el uso de recursos, optimizando tu pipeline y entorno tal como explicamos en nuestro artículo sobre cómo acelerar builds en Docker con caché.
Consideraciones finales
Dominar la configuración de liveness y readiness probes es el punto de inflexión entre una aplicación frágil que colapsa al primer signo de estrés y un sistema resiliente que se recupera por sí mismo. Al separar la lógica de vivencia de la lógica de preparación, proteges tus contenedores contra reinicios agresivos y evitas que los usuarios accedan a instancias que aún no están listas. Recuerda ajustar los parámetros de tiempo según las necesidades reales de tu software, evitando pruebas excesivas que consumen recursos sin aportar valor real. Con estas prácticas implementadas, tu arquitectura gana la estabilidad necesaria para operar sin sobresaltos a gran escala.