Conociendo Fn (parte 1): Plataforma Serverless MultiCloud
Hoy empezamos una nueva serie acerca de Fn Project, una plataforma open source Serverless para contenedores que puede ejecutarse en cualquier lugar (Cloud o CPD), fácilmente extensible y que permite programar las funciones en Java, Python, Go, Node.js, Ruby o C#.
A lo largo de diferentes entradas, iremos conociendo en qué consiste esta plataforma, desde su concepto a otros aspectos más avanzados, tales como:
- Configuración avanzada.
- Cómo integrar Fn con Kubernetes.
- Cómo integrar FDK for Java con GraalVM para generar funciones Java que ejecutan más rápido.
- Uso de Fn Flow para orquestación de funciones.
- Cómo integrar Fn con Spring Cloud Functions (la plataforma FaaS de Spring).
- Cómo crear una Función de una imagen Docker.
Conociendo Fn
A lo largo de la entrada de hoy, vamos a explicaros un poco en qué consiste esta plataforma serverless de tipo multicloud.
¿Serverless?
Podríamos decir que se trata de una tendencia en Arquitectura de software que reduce la noción de infraestructura, ya que aunque esta tendencia sigue requiriendo servidores, los desarrolladores no tienen que preocuparse por el balanceo de carga, el multihilo o cualquier otro tema de infraestructura, ya que la propia plataforma elegida gestiona los recursos, permitiendo a los desarrolladores centrarse únicamente en su código.
En la actualidad hay muchos frameworks y plataformas serverless de proveedores Cloud como AWS Lambda (Amazon), Azure Functions (Microsoft), Cloud Functions (Google), Cloudflare Workers (Cloudflare) u OpenWhisk (IBM). Estas soluciones Cloud cobran por el número de invocaciones y sólo pueden desplegarse en este proveedor.
En ese sentido, Fn Project es Cloud-agnostic, ya que puede ser desplegada en cualquier entorno que soporte Docker (se integra con Kubernetes) y cuenta con el soporte de Oracle.
Comparando serverless con MSA
En serverless, cada trozo de código se denomina Función, y un proveedor serverless proporciona funciones como servicio (FaaS; Function As A Service), incluyendo todo lo necesario para aprovisionar, escalar, parchear y mantener el entorno.
En una Arquitectura de Microservicios (MSA; Microservices Architecture), en lugar de crear un gran servicio monolítico, el servicio se descompone en servicios más pequeños que proporcionan el mismo conjunto de funciones. Esto simplifica el desarrollo y la creación de servicios web; sin embargo, cada microservicio sigue ejecutando su propio servidor, que debe ser escalado y gestionado.
Por tanto, vemos como FaaS lleva las cosas un paso más allá:
Arquitectura Fn
Una implementación típica de Fn podría ser como esta:
Donde un balanceador de carga proporciona un front-end a varios servidores Fn, cada servidor gestiona y ejecuta el código de la función según sea necesario; los servidores pueden ser escalados hacia arriba o hacia abajo según sea necesario. Con Fn, cada función es un contenedor Docker.
Desplegando Fn
El proceso de despliegue de un proyecto de Fn se descompone en tres pasos:
- Se construye una imagen Docker con el código de la función (y se aumenta el número de versión)
- Se sube la imagen de contenedor al Registro Docker (DockerHub por defecto).
- Se crea un trigger para su ejecución en el servidor.
De modo que, al llamar a la función vía URL o comando, el contenedor se ejecuta y devuelve los resultados:
Ejemplo práctico en Java
A continuación vamos a ver un pequeño ejemplo de cómo desplegarlo vía Java:
Instalando Fn
El primer paso consistirá en instalar Fn. Esto se puede hacer de diferentes maneras, dependiendo del entorno en el que nos encontremos. Así, en Linux y macOS únicamente tendríamos que ejecutar el siguiente script:
curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
En un entorno Windows, lo más sencillo es instalar previamente Docker, y una vez que esté listo, descarganos Fn desde el repositorio del proyecto. Una vez instalado, tendremos que añadir el ejecutable fn.exe al PATH.
Lanzando Fn
Ejecutar Fn es tan sencillo como lanzar un «fn start» en la línea de comando. Esto iniciará Fn en modo Single Server Mode (como imagen Docker), utilizando una base de datos y una cola de mensajes embedidas.
En Windows si tenemos alguna versión antigua de Docker instalada nos puede saltar un error como este:
Solucionar este problema no es complicado, ya que únicamente tendremos que lanzar manualmente el ejecutor con la siguiente línea de código:
docker run --memory 1024M --memory-swap 1024M --privileged --rm --name functions -it -v /var/run/docker.sock:/var/run/docker.sock -v D:/fn/data:/fn/app/data -p 8080:8080 fnproject/fnserver
En mi caso, lo que hecho es actualizar a WSL2 (el subsistema de Windows para Linux), instalar una distribución Linux en Windows (Ubuntu) y habilitar Docker para que en lugar de usar Hyper-V funcione nativamente sobre WSL2, esto me permite ejecutar Docker desde esta distribución Linux:
Creando la primera función
Seleccionaremos la carpeta donde queramos trabajar, y ejecutaremos el siguiente código:
fn init --runtime java java_fn_example
Esto inicializará el runtime de Java. Seguidamente nos moveremos al directorio «java_fn_example», en donde comprobaremos que se habrá creado un archivo «pom.xml» (proyecto Maven), un «func.yaml» (Descriptor Fn) y una carpeta «src» para los fuentes.
Para crear la aplicación, lanzaremos el siguiente comando:
fn create app java_fn_example-app
Aquí es interesante que nos fijemos en la clase que implementa la función («HelloFunction»), que se encuentra localizado en «src/main/java/com/example/fn»; aquí veremos que tenemos implementado el mítico «Hello» + nombre:
Despliegue de la función
Para desplegar la función, usaremos la función creada por defecto. Para poder hacer el despliegue en nuestro entorno local, lanzaremos (añadimos el verbose):
fn deploy
--verbose --appjava_fn_example-app
--local
Esto compilará el proyecto Maven, generando la imagen Docker.
Ejecutando
Ahora que ya tenemos desplegada la función, podemos pasar a ejecutarla. Para empezar. lo haremos con el Fn CLI:
fn invoke java_fn_example-app java_fn_example
También podemos invocarlo a través del endpoint que habilita el propio Fn, para esto primero ejecutamos la siguiente línea de código:
fn inspect
functionjava_fn_example-app java_fn_example
Si capturamos la URL que aparece, nos será posible invocarla vía curl:
curl -X "POST" http://localhost:8080/invoke/01F00Z4AHENG8G00GZJ0000007
NOTA: Como es arquitectura Serverless, podemos ver que la imagen de la función no está en ejecución como tal, sino que es el FnServer el encargado de lanzarla:
Completando el ejemplo
Una vez que hemos visto cómo se construye una función, vamos a completar la función de ejemplo «HelloFunction». Para eso, en lugar de un String, lo configuraremos para que reciba un JSON como entrada y devuelva otro JSON.
El FDK nos ofrece una utilidad para mapear JSON a clases en base al nombre de los atributos, de modo que si envío un JSON como este: { «name»: «Luismi» } y dejo la función así automáticamente, el FDK nos mapeará name del JSON sobre la clase Input:
Vamos a hacer un fn build para reconstruir la función. Sin embargo, esto va a fallar, pues no hemos actualizado el test de la función, por lo que procederemos a actualizar el test, y seguidamente a realizar el build:
Hecho esto, podremos invocarlo con la siguiente línea de código:
curl -X "POST" -H "Content-Type: application/json" -d '{"name":"Luismi"}' http://localhost:8080/invoke/01F00Z4AHENG8G00GZJ0000007
¿Y que vamos a recibir? Algo similar a esto:
Triggers
Otra funcionalidad interesante es la de los triggers. Un Trigger representa un punto de entrada para la invocación de funciones. Cada tipo de Trigger requiere una configuración específica que se definen dentro del archivo func.yaml, como por ejemplo:
Tras hacer el despliegue, esto nos va a permitir invocar ahora a la función por su endpoint: http://localhost:8080/t/java_fn_example-app/hello
Interfaz de usuario para Fn
Por último, no queremos dejar de comentar el proyecto «UI for fn», que como su propio nombre indica, es un interfaz de usuario para ver el estado de nuestra instancia de Fn.
Para lanzar este entorno gráfico, lanzaremos la siguiente línea de código:
docker run --rm -it --link fnserver:api -p 4000:4000 -e "FN_API_URL=http://api:8080" fnproject/ui
Esto lanzará el UI, donde podremos ver las aplicaciones que tenemos creadas, las que están en ejecución, y si hay en cola:
Algo práctico de esto es que nos permitirá también probar nuestra función:
Con esto damos por terminada esta primera entrada sobre Fn. Esperamos que os haya parecido interesante, y nos vemos la semana que viene en la próxima entrada.
Cualquier duda que os surja, por favor dejadnos un comentario.
Pingback: Conociendo Fn (parte 2): Generando una función Fn con Java y GraalVM – Onesait Platform Blog
Pingback: Conociendo Fn (parte 3): crear una función en Python – Onesait Platform Blog
Pingback: Creando una función de Spring Cloud Function sobre Fn Project – Onesait Platform Blog
Pingback: Release 3.2.0-Legend de la Onesait Platform – Onesait Platform Blog
Pingback: Serverless en 2021 y la Onesait Platform – Onesait Platform Blog