lunes, 19 de abril de 2021

Readiness

¿Cuánto tiempo pasa desde que una aplicación es arrancada hasta que es capaz de desempeñar su trabajo con normalidad?

 

En aplicaciones de escritorio hay mucha variación, tenemos algunas en las que prácticamente ese tiempo es nulo, mientras que en otras, es tan elevado, que se recurre a técnicas como la splash screen.

 

Sin embargo en aplicaciones web en general, y en API's REST en particular, no solemos fijarnos tanto en esto, ya que el tiempo usualmente es mucho más pequeño.

Fijaos en esta sencilla API escrita en .net 5 (un solo fichero): 




¿Cuánto tardará en empezar a atender peticiones desde que sea iniciada? ¿Algunos milisegundos? Es posible. Fijaos que ese pequeño tiempo puede generarnos problemas, sobre todo si estamos en escenarios de auto-escalado o si buscamos despliegues sin parada (Aquí te dejo una sesión en la que hablo de este tipo de despliegues).


Por otro lado, imagina una aplicación que necesite descargar configuración o secretos desde un recurso externo antes de poder empezar a atender peticiones. En este caso ese tiempo será muy superior.


Mi definición de "readiness"


"Es el estado de una aplicación en el cual está capacitada para hacer su trabajo con normalidad"

En el supuesto anterior, la aplicación arranca y necesita cierto tiempo para descargar recursos externos (secretos u otra configuración). Una vez hecho está "ready", puede hacer su trabajo con normalidad y por tanto atender peticiones de usuario.



Imagén explicativa de Readiness. Un pod arranca y necesita tiempo hasta que puede aceptar tráfico


¿Qué es un readiness probe?


Es una sonda o verificación que nos indicará si una aplicación se encuentra en un estado de "ready" o "not ready". En base al resultado de la verificación, se enviará tráfico o no a la aplicación.

Veámoslo en el caso de kubernetes. Allí, los pods se crean y destruyen por diferentes motivos, alguno de los cuales no requieren nuestra intervención (un pod es movido de nodo, o simplemente falla y es rearrancado). Por tanto no sería nada deseable que un pod que aún no esté listo recibiese tráfico, ya que generaría errores.

Para conseguirlo, debemos definir una "readiness probe" en nuestros deployments, del siguiente modo:



En este caso he definido un probe http, aunque no es la única opción disponible, ya que también podemos definir probes tcp o probes basados en comandos. En la documentación oficial podemos verlo.

 

Como veis, he definido un periodo de ejecución de la sonda de 5 segundos, además de un umbral de 2 (threshold), que os paso a explicar:


  • Inicialmente, un pod arranca en estado "Not ready"
  • Una vez que supera la sonda de readiness pasa a estado "Ready"
  • Si la sonda falla 2 veces seguidas (aquí está ese umbral), pasa de nuevo a estado "Not ready", y no recibirá tráfico.

Solo hay un matiz a lo anterior: si no hemos definido el Readiness en nuestro deployment, el pod siempre será considerado como "Ready".

 Con todo esto, mi deployment de kubernetes queda así:



 


¿Por qué es importante el readiness en escenarios de auto-escalado?


Lo mencioné de pasada antes, merece explicarlo:

 

Si tenemos reglas de autoescalado, tarde o temprano, y en base a estas reglas, nuevos pods serán creados para atender la creciente demanda. En esos casos, una vez que el pod es creado, empezará a recibir tráfico de inmediato, a no ser que definamos las probes de readiness adecuadas. 

 

Si recibe tráfico de inmediato, y no tenemos reglas de readiness, vamos a tener momentos "problemáticos", que son esos tiempos muertos desde que un pod arranca hasta que está listo para atender tráfico.

 

Sin embargo si definimos sondas de readiness, el nuevo pod no recibirá tráfico hasta que éstas sondas son satisfactorias, evitando así cualquier tipo de downtime.



¿Hay más tipos de sonda?


Si, tenemos sondas de Liveness y de Startup, las veremos en otras entradas.


Espero que os haya resultado interesante.


No hay comentarios:

Publicar un comentario