Cerrar panel

Cerrar panel

Cerrar panel

Cerrar panel

Serverless

La arquitectura serverless también conocida como FaaS (Functions as a Service), habilita la ejecución de una aplicación mediante contenedores efímeros y sin estado; estos son creados en el momento en el que se produce un evento que dispare dicha aplicación. Contrariamente a lo que nos sugiere el término, serverless no significa «sin servidor», sino que éstos se usan como un elemento anónimo más de la infraestructura, apoyándose en las ventajas del cloud computing.

En este post exploramos, dejando de un lado el hype que acompaña al término serverless, las posibilidades que nos ofrece a nivel de arquitectura y desarrollo de aplicaciones. También estudiamos las principales alternativas de uso en clouds públicas y privadas.

especial-labs-v2_serverless

Beneficios de serverless

La principal ventaja de una arquitectura serverless es la posibilidad de que el desarrollador se despreocupe de la gestión de la infraestructura sobre la que se ejecuta su servicio (función) y centrarse en la funcionalidad: el ciclo completo de desarrollo se simplifica.

También nos proporciona un nivel elevado de desacoplamiento entre los diferentes servicios, favoreciendo el desarrollo de arquitecturas basadas en microservicios. Esto facilita mucho el ciclo de vida y los despliegues continuos, además de simplificar los rollbacks si fueran necesarios.

Por último, una arquitectura serverless nos posibilita reducir el gasto en infraestructura, generando costes únicamente cuando se realiza una petición, y por tanto, cuando la función se ejecuta.

Arquitectura serverless

Una función que se ejecuta en una arquitectura serverless debe ser procesada por un wrapper del lenguaje apropiado (Python, NodeJS, etc) que es capaz de recibir los datos de entrada, entregarlos a la función, ejecutarla y enviar los datos de salida. Cada wrapper genérico de un determinado lenguaje se denomina entorno. Estos entornos son instanciados en forma de contenedor cuando una función necesita ser ejecutada.

Cuando un desarrollador carga o modifica una función en la infraestructura FaaS, se crea un contenedor que contiene el entorno necesario para ejecutar la función, junto con la función en cuestión. El contenedor resultante se almacena en un registro accesible por la infraestructura del FaaS. Igualmente, se crea también la entrada correspondiente en el API gateway que se encargará de encaminar la petición (generalmente REST HTTP) y arrancar el contenedor o contenedores (dependiendo de la concurrencia que tenemos configurada) que alojan la función que deben procesar esa petición. Si el contenedor de la función no está disponible, se lanza en el momento en el que llega la petición. Tras atender la petición, el contenedor puede destruirse inmediatamente o tras un periodo definido.

El tiempo necesario para que una función esté lista para empezar su ejecución es de unos cientos de milisegundos, dependiendo de la tecnología usada. Este valioso tiempo de latencia puede ser reducido mediante las llamadas hot functions, que mantienen la instancia en ejecución para evitar el overhead de arranque del contenedor, mejorando sensiblemente el throughput en el caso de alta demanda del servicio en cuestión.

Las infraestructuras serverless actuales usan RPC para delegar la ejecución de un REST API Gateway sobre un conjunto de servidores.

Estado del arte y opciones de despliegue en cloud pública

Las principales proveedores de cloud pública ofrecen su versión de FaaS, cada uno como un producto con sus propias APIs y tecnologías:

El caso más extendido en la actualidad para el uso de arquitecturas serverless es el uso de FaaS como servicio de un proveedor de cloud pública, como Amazon Lambda, Google Cloud Functions o Microsoft Azure Functions. En este caso el servicio es gestionado y servido por el proveedor.

En el caso de AWS Lambda se han publicado muy pocos detalles internos de su arquitectura. Según su documentación oficial, se usa un modelo de contenedores, aunque no mencionan nada del orquestador que utilizan internamente.

En Google Cloud Functions las funciones se ejecutan en entornos nativos con Node.js. Existe un emulador para probar las funciones en un entorno local, CI/CD antes de publicarlas.

Azure Functions, pese a parecer un servicio similar, se trata de una implementación radicalmente diferente. Las Azure Functions son ejecutadas sobre Azure WebJobs. Microsoft tiene publicado su entorno de ejecución en GitHub.

Estado del arte y opciones de despliegue en cloud privada

Para despliegues on-premises, existen diferentes opciones, dependiendo de si se despliegan sobre baremetal, un IaaS como OpenStack, o un PaaS como Kubernetes o Mesos:

A la hora de implementar una arquitectura serverless on-premises, ésta puede ser desplegada como una aplicación cualquiera, o ser integrada como un servicio ofrecido por un IaaS o un Paas. Iron Functions es un ejemplo del primer caso, donde el usuario despliega FaaS sobre servidores físicos o sobre un espacio privado de un proveedor de cloud: un tenant de OpenStack, un VPC de AWS, etc.

En el segundo caso se busca la integración con el servicio de infraestructura, aprovechándose de la integración de las funcionalidades de multi-tenancy, control de usuarios, etc que provee el software de IaaS o PaaS. El proyecto OpenStack Picasso es un intento de integrar Iron Functions como un servicio más de OpenStack, mientras que Fission es implementa FaaS sobre Kubernetes. Ambos implementan un FaaS, pero con un enfoque totalmente diferente.

OpenStack Picasso despliega Iron Functions en la infraestructura, y le añade los servicios de control de usuarios de OpenStack Keystone. Sin embargo, no existe control de OpenStack sobre la propia infraestructura que ejecuta las funciones: ambos mundos funcionan de manera independiente. Iron Functions actúa de forma externa a OpenStack. Por tanto, no existen los conceptos de cuotas, ni el control de nodos de cómputo, ni multi-tenancy para los contenedores del FaaS. Tan solo se permite crear funciones privadas que son visibles únicamente para los usuarios de un tenant de OpenStack.

Tanto Fission como Iron Functions usan contenedores Docker para contener y ejecutar nuestra función lambda.

El caso de despliegue de FaaS sobre Kubernetes es probablemente el más interesante, puesto que nos permite unir de forma sencilla microservicios tradicionales con los implementados usando serverless. Todo de forma integrada en Kubernetes, usando los servicios que proporciona un cluster de Kubernetes, como monitorización, agregación de logs y publicación de servicios.

Tiempo de arranque en frío y hot functions

Iron Functions crea un contenedor por cada ejecución. El tiempo medio de arranque de un contenedor ronda los 200~300ms. Este tiempo es demasiado elevado para ofrecer unas latencias aceptables para una petición HTTP en la mayoría de los casos. Aquí es donde entran en juego las llamadas Iron Hot Functions/Containers. Este tipo de funciones permiten mantener los contenedores arrancados mientras se estén recibiendo peticiones y, por tanto, evitar el tiempo de arranque en frío para segundas y subsiguientes peticiones.

Las hot functions permiten mantener los contenedores arrancados mientras se estén recibiendo peticiones, evitando el tiempo de arranque en frío para segundas y subsiguientes peticiones.

Se sabe poco sobre la implementación de este mecanismo de Hot Functions en Iron Functions, ya que en la propia documentación de Iron mencionan únicamente que utilizan la entrada y salida estándar del sistema para operar los Hot Containers. Además, las Hot Function de Iron requieren de código específico para funcionar debido a que modifican internamente el evento que envían a la función.

En el caso de Fission, existe un pool de contenedores que ejecutan las funciones, y están permanentemente esperando un evento, por lo que el tiempo de arranque en frío es mucho menor (~100msec), a costa de consumir esos recursos aunque no existan peticiones.

Laboratorio: Probamos serverless con AWS, IronFunctions y Fission

Hemos hecho nuestra propia batería de pruebas para comparar el rendimiento de cada de las las tecnologías. Todas las pruebas excepto las de AWS Lambda se han realizado en el mismo PC con las siguientes especificaciones:

  • CPU: Intel i5-4310M CPU @ 2.70GHz
  • RAM: 8GiB DDR3 @ 1600MHz
  • HDD: 320 GB @ 7200RPM

Las pruebas se han realizado con Siege. El test consiste en estresar durante 10 segundos los endpoints de las funciones con una concurrencia de 25 peticiones.

Figura 1. Peticiones por segundo en las diversas plataformas analizadas (A mayor número de peticiones por segundo, mejor)

Figura 2. Tiempo de respuesta de la primera petición para cada plataforma analizada. Menor latencia, mejor. También indicamos el tiempo del inicio en «frío»..

Valor de negocio inmediato

Todo nuevo cambio de paradigma debe llevar unos beneficios intrínsecos que justifiquen la adopción del nuevo modelo. En el caso de serverless encontramos algunos de estos beneficios inmediatamente:

  • Reducción de los tiempos de desarrollo y time-to-market: el contrato con la infraestructura permite al desarrollador concentrar su esfuerzo en el desarrollo de la funcionalidad, minimizando el tiempo dedicado al diseño de la escalabilidad y del entorno de ejecución.
  • Optimización de los recursos, sin dedicar tiempo a la escalabilidad y dimensionado de nuestra aplicación conseguimos una optimización completa a todos los niveles:
    • Arquitectura completa: no es necesario dimensionar y asignar una máquina a un microservicio, y por tanto, no habrá recursos sin utilizar, como sucede en los despliegues erróneos y/o sobredimensionados. Esto supone ahorros inmediatos en despliegues en nubes públicas que están inactivas por largos periodos de tiempo.
    • Escalado automático por función: ante un pico de demanda de una o varias funciones, éstas escalarán independientemente, optimizando los recursos disponibles a las funciones que realmente lo necesitan.
  • Mejoras en arquitecturas actuales basadas en procesamientos masivos de información  (batch, ETLs, etc). En estos casos de uso las latencias no son tan relevantes, pero nos permite evolucionar de las tradicionales arquitecturas batch, basadas en ficheros y Job Control Languages (JCL), a modelos más orientados a flujo (stream-oriented). Esto a su vez debería facilitar el paso de modelos puramente batch a real-time, o near real-time.

Apuesta de futuro

La industria está adoptando rápidamente las arquitecturas serverless. Casos de éxito como Pokemon Go, o SnapChat, donde una demanda masiva no supuso un problema para la escalabilidad del servicio, avalan la arquitectura. En un futuro cercano nos encontraremos con algunos cambios que harán de Lambda serverless una arquitectura adecuada para la mayoría de los casos.

Desde el punto de vista del desarrollador, serverless sigue teniendo peculiaridades a las que adaptarse, como su naturaleza stateless. Sin embargo, los inconvenientes son mucho menores que los derivados del despliegue de una arquitectura tradicional.

Triggers de funciones

Las infraestructuras serverless actuales descansan sobre el protocolo HTTP, lo que las hace más adaptables. Sin embargo, en la arquitectura serverless, el protocolo de comunicación es una pieza más, lo que permitirá cambiar el protocolo y adaptarlo a las necesidades de cada caso.

También permitirá crear pequeñas piezas de código para usar nuestra arquitectura con otras fuentes de datos más allá de HTTP; por ejemplo, Kafka o triggers de infraestructura (apagado de una máquina, uso intensivo de un recurso de la red, una métrica de negocio concreta).

En este aspecto Amazon Lambda lidera el mercado ofreciendo una integración transparente con todos sus productos, pudiendo disparar funciones ante eventos en S3 o SQS. Fission también responde a algunos eventos concretos de Kubernetes.

Composición de funciones

 

En el futuro se alcanzará la posibilidad de combinar funciones. Esto permitirá definir pipelines de negocio. Amazon step functions empieza ya a explorar esta posibilidad. Estos pipelines permitirán una colaboración tecnológica sin precedentes de personas con set de habilidades muy diversos, reduciendo los costes de contratación al no tener que concentrarse todo el desarrollo en una tecnología en concreto.

En arquitecturas tradicionales, los programadores deben estar al corriente de los componentes auxiliares a la función de negocio específica, como seguridad, log, etc para poder crear un servicio completo. En las arquitecturas lambda puras, se pueden crear estos mecanismos de seguridad y control como parte de la infraestructura, y encadenarlos a la función de negocio específica. Los sistemas Lambda que permiten composición posibilitan habilitar mecanismos auxiliares o complementarios sin que el desarrollador que implementa una función específica deba conocerlos. Esto permite de nuevo al programador centrarse en el valor que aportará su código; también reduce la cantidad de experiencia necesaria para poner un servicio en producción. Además al estar las funciones auxiliares integradas en la plataforma, no es posible “saltarse” esta regulación, lo que confiere seguridad al sistema y minimiza posibles riesgos derivados de su incorrecta explotación.

Las arquitecturas lambda funcionan en streaming por naturaleza, lo que permitirá el uso de técnicas avanzadas de redirección de tráfico, despliegue y testing de soluciones. Algunas técnicas conocidas que se pueden llevar a cabo son:

  • A / B testing
  • Canary Release
  • Parallel testing

La reducción de particularidades para cada caso permitirán centrarse más en qué desarrollar frente al cómo desarrollarlo, reduciendo de esta forma el Time to Market y también el riesgo de errores en entornos de producción.

El scheduling y la optimización en la localización de los recursos tiene también un camino para recorrer. El uso de arquitecturas serverless permitirá predecir mejor cómo escalar las funciones que componen un servicio de manera independiente, en lugar de intentar predecir un servicio completo. Esto abre la puerta al uso de técnicas de Machine Learning para hacer escalado predictivo (frente al reactivo) de la infraestructura dependiendo de las características del tráfico.

Conclusiones

Las arquitecturas lambda serverless permiten evolucionar la composición de servicios de forma atómica (funciones lambda) y escalable (serverless). Todo ello se traduce para las aplicaciones reales de negocio en:

  • Reducción de los costes de implementación y operación, gracias al autoescalado que ofrecen las arquitecturas lambda desde su definición.
  • Simplificación del mantenimiento y evolución de la aplicación, gracias a la atomicidad de las funciones
  • Reducción de los tiempos de desarrollo: mejora en el time-to-market.
  • Incremento de la seguridad, gracias a la posibilidad de ser implementado de forma externa a la función lambda principal.
  • Incremento de la fiabilidad.

Actualmente las arquitecturas serverless/lambda están limitadas en cuanto a la funcionalidad que podemos implementar en ellas. Queda un largo camino por recorrer en cuanto a soporte de lenguajes, refinamiento interno de la arquitectura y uso de APIs diferentes a REST para poder ser una alternativa arquitectónica a cualquier aplicación.

En cloud privada, la propuesta tecnológica más interesante para su aplicación a día de hoy puede ser la de Fission.io, que funciona sobre la plataforma PaaS más usada en la actualidad: Kubernetes. Creemos que el enfoque de basar Fission sobre un PaaS preexistente permite centrar el esfuerzo de desarrollo en el core de la aplicación (valor diferencial), frente a otros enfoques que construyen la solución desde cero (IronFunctions). Además, abre la puerta a despliegues en nubes híbridas: GKE es la solución de Google Compute Platform para el despliegue de contenedores en la cloud pública.

En cuanto a los servicios de cloud pública, el vendor lock-in que provoca usar alguno de los entornos que Amazon, Google o Microsoft proveen es una desventaja que desincentiva su adopción. En los servicios analizados, la novedad y la falta de estandarización por el momento supone una barrera a su adopción.

Sin embargo, hay razones de peso y casos de éxito en producción suficientes como para considerar esta tecnología (además de la metodología de diseño y desarrollo asociada) como una de las tendencias más importantes para el despliegue con éxito de aplicaciones autoescalables y con un time to market impresionantemente bajo. De hecho, ya se usa en tareas críticas como la vigilancia del mercado financiero en Estados Unidos por parte de Finra, o los casos de éxito ya comentados de Pokémon Go y SnapChat.

Por todo ello, es necesario familiarizarse con esta tecnología mientras evoluciona, preparando y eligiendo ya aplicaciones susceptibles de desarrollarse sobre este paradigma. Este conocimiento nos permitirá tener en el futuro una ventaja competitiva sobre arquitecturas más conservadoras, especialmente cuando se enfrenten a necesidades de escalabilidad masivas.

Te animamos a participar enviando tus comentarios a BBVA-Labs@bbva.com  y, si eres de BBVA, aportando tus propuestas de publicación.

Referencias