lunes, 26 de abril de 2021

Liveness

Hablábamos en el artículo anterior sobre Readiness, una sonda de kubernetes que indica cuando un pod está listo para atender tráfico, dejándo la plataforma de enviárselo en caso de no superar la sonda. Aquí puedes echarle un ojo.

Un pod puede no ser capaz de atender tráfico temporalmente (está arrancando por ejemplo) o debido a un error del que no pueda recuperarse solo. Para este segundo caso tenemos otro tipo de sonda, llamada Liveness, que es explicada por David Fowler en el siguiente tweet:

 

Definición de liveness de David Fowler

Esta sonda "pregunta" a un pod si sigue vivo, para en caso contrario reiniciarlo. Podemos verlo de un modo muy claro en la siguiente imagen (cortesía de la documentación de Google Cloud Platform):

 

Liveness en funcionamiento

 

Como veis, si la sonda no se supera, el pod es reiniciado, pudiendo esto resolver un problema del pod, que le impidiese hacer su trabajo con normalidad.

 

¿Siempre necesito definir esta sonda?

Para poder responder debemos entender el ciclo de vida de un pod, que podemos encontrar en la documentación oficial.
 
Allí se hace referencia a que los contenedores de un pod (si, no olvidemos que en un pod se ejecutan 1 o más contenedores) pueden ser reiniciados cuando terminan, dependiendo de la "restart policy" definida.
 
Esta política admite tres valores:

  • Always (valor por defecto)
  • On failure
  • Never

 
Salvo que utilicemos la opción "never", nuestros contenedores serán rearrancados después de terminar, usando un retardo exponencial (10s, 20s, 40s…) que está limitado a un máximo de hasta 5 minutos.
 
Si fijamos el valor "On failure" solo serán rearrancados contenedores que finalicen con un valor de retorno distinto a 0.
 
Explicado lo anterior, parece que dejando el valor por defecto, vamos a conseguir que nuestros pods siempre esten "vivos", ya que si sus contendores acabasen, por el motivo que fuere, serían reiniciados.
 
Pero la clave es: ¿mi contenedor siempre va a terminar si encuentra algún error o no es capaz de funcionar correctamente? ¿Estamos seguros de que no va a entrar en un estado de dead lock? ¿Y en un bucle infinito?
 
Si no estamos seguros de poder responder afirmativamente a las preguntas anteriores, mejor será definir una sonda de liveness, que se encargue de reiniciar el pod si este no es capaz de responder satisfactoriamente.


Definiendo la sonda de liveness

Debemos hacerlo en nuestros deployments:

La sonda anterior tratará de conectar con el puerto 80 cada 5 segundos, y en caso de poder hacerlo la prueba se considerará exitosa. En caso contrario, tras dos fallos consecutivos, el pod será reiniciado.
 
En este caso he definido un probe tcp, aunque no es la única opción disponible, ya que también podemos definir probes http o probes basados en comandos. En la documentación oficial podemos verlo en detalle, no obstante aquí os dejo un fragmento de una sonda http:
Ten en cuenta que tu eres el responsable de impementar el endpoint /healthy en tu aplicación. En el mismo puedes devolver Ok sin más (sonda "tonta") o realizar comprobaciones avanzadas, como tratar de ver si la base de datos está accesible (sonda "lista").


¿Http, tcp o comandos?

No es una respuesta sencilla, pero de entrada diría que una buena opción para empezar sería la siguiente:

  1. Http si está disponible
  2. Tcp si el pod no "habla" http
  3. Comando si el pod no "escucha" peticiones (hace tareas batch por ejemplo)

Pero no se trata de una "ley" a cumplir siempre, aquí lo que mejor funciona es el clásico "depende". Depende de tu aplicación y su contexto :-)
 
Lo que si me parece interesante es comentar que si tu pod tiene su contenedor principal y un contenedor sidecar, tipo proxy inverso nginx por ejemplo, una sonda tcp puede resultar insuficiente: podría conectar con el nginx sin problema, pudiendo estar el contenedor principal bloqueado. 

 

¿Cómo sería una sonda basada en un comando?

Como comentaba, si tu pod no escucha peticiones, no son viables las sondas http o tcp, y debemos basarnos en comandos.
 
Un ejemplo sería ver si el pod está generando periódicamente un fichero concreto en un directorio. En caso de que el pod no estuviese vivo, no podría generar el fichero y la sonda fallaría.
 
Ese script status_check.sh será el encargado de comprobar que el fichero existe y que ha sido creado recientemente (basándose en su fecha). En caso de no encontrar el fichero o detectar que no es reciente, el script saldrá con error haciendo que la sonda no se supere.

Recursos

Os dejo un par de enlaces interesantes:

La documentación oficial, donde entran en detalle de todas las configuraciones que podemos definir en una sonda, como el periodo de ejecución y los umbrales para considerar una sonda como exitosa o fallida.

Por otro lado, os dejo un proyecto opensource, Xabaril Health Checks, que si trabajais en .net core (o net 5) os ayudará a implementar sondas (readiness o liveness) basándoos en los health checks ofrecidos por la plataforma.

Espero que esta entrada os haya gustado. Saludos

No hay comentarios:

Publicar un comentario