¿Que es Azure Functions?
Azure Functions es una opción serverless en Azure. Es muy atractiva para escenarios de despliegues on-demand de manera rápida, eficiente y escalable sin necesidad de administrar practicamente nada de la infraestructura subyacente.
La idea principal de este servicio es que “vos provees el código y Azure se encarga del resto”. Aunque en muchas ocaciones, esto se acerca a la realidad, en la mayoría de los casos debemos adaptar el código para que pueda correr como una function app.
Functions soporta lenguajes como C#, Java, JavaScript, PowerShell, Python y otros como Rust y GO.
Tenemos diferentes tipos de Planes para Azure Functions:
- Consumption plan:
- Pay-as-you-go, el billing solo incurrirá sobre el tiempo que el codigo este corriendo.
- Escalabilidad automatica.
- Tiempo de ejecución maximo: 5 min.
- Premium plan:
- Mayores opciones de conectividad (vnet integration).
- Mejor rendimiento.
- Sin límite de tiempo.
- Billing sobre instancias reservadas.
- Dedicated (App Service):
- Utilizaremos un App Service Plan de base.
- Mayor control sobre la infra.
- Facturación basada en la infraestructura reservada, independientemente de las ejecuciones de las funciones.
Es un servicio Event-based, y tiene varios escenarios de “casos de uso”. Aquí algunos de ellos:
- Procesar cargas de archivos: Ejecuta código cuando un archivo se carga o cambia en un Blob Storage.
- Ejecutar tareas programadas: Ejecuta código de limpieza de datos en intervalos de tiempo predefinidos.
- Responder a cambios en bases de datos: Ejecuta lógica personalizada cuando se crea o actualiza un documento en Azure Cosmos DB.
- Crear sistemas de mensajes confiables: Procesa colas de mensajes utilizando Queue Storage, Service Bus o Event Hubs.
- Construir una API web escalable: Implementa un conjunto de puntos finales REST para tus aplicaciones web usando disparadores HTTP.
En este ejemplo utilizaremos Azure Functions para implementar una API escalable.
Python FastAPI framework
Estaremos realizando el deploy de una Python FastAPI. Utilizaremos el codigo hospedado en el repo madsblog-fastapi-on-azure-functions:
- Como indica la información de este Fork, se trata de un Azure Sample de una FastAPI de Python.
- Para correr una FastAPI en Azure Functions es necesario realizar algunas declaraciones a nivel de codigo. En este caso el codigo ya está actualizado para poder ejecutarse en la App.
- Se agrega azure-functions al archivo de prerrequisitos:
- Archivo host.json:
- En este archivo se configuran:
- Aspectos de Logging en Application Insights para la función.
- Extensiones: aquí se configura el HTTP Trigger para la ruta /. No se agrega ningun prefijo adicional.
- La root folder contiene el archivo function_app.py que inicializa/llama a la AsgiFunctionApp usando la FastApi App importada.
- En la carpeta WrapperFunction el archivo _init_.py define la FastApi que llamos en nuestro archivo function_app.py.
Configuración de Autorización
Realizaremos un solo cambio en el codigo de nuestra API y será modificar el Nivel de Autorización. Existen 3 tipos de niveles de Autorización para las API:
- Anonymous:
- Cualquiera puede invocar la función, no se requiere ninguna clave.
- Esto es útil para funciones públicas que no requieren ningún tipo de autenticación o autorización.
- Function:
- Se requiere una clave específica de función para invocar la función.
- Cada función tiene su propia clave, lo que significa que la clave de una función no puede ser utilizada para invocar otra función, incluso si ambas funciones están en la misma aplicación de Azure Functions.
- Esto es útil cuando quieres restringir el acceso a una función específica y/o cuando quieres poder rotar las claves por función.
- Admin:
- Se requiere una clave maestra (también conocida como clave de administrador) para invocar la función.
- Esta clave permite el acceso a cualquier función dentro de la aplicación de Azure Functions, por lo que debe ser tratada con un nivel adicional de cuidado.
- Esto es útil cuando se necesita un nivel elevado de control o acceso administrativo a todas las funciones.
- System (específico para ciertos triggers como Timer y Durable Functions):
- Es similar a Admin, pero también permite el acceso a sistemas internos de Azure.
- No es típicamente utilizado para funciones basadas en HTTP.
- User (específico para Azure Functions con EasyAuth):
- Requiere que un usuario esté autenticado para invocar la función.
- Funciona en conjunto con el servicio de autenticación de Azure App Service (también conocido como EasyAuth).
Este caso modificaremos el Nivel de Authorization a Function:
- Modificaremos la siguiente linea de codigo eb el file function_app.py:
- Push de los cambios al repo:
Para desplegar una Azure Function podemos seguir las indicaciones del siguiente video
Creación de Worflow en GitHub Actions
Para la creación de nuestro Workflow en GitHub actions debemos:
- Asegurarnos que este habilitado Actions en nuestro repositorio:
- En el directorio .github/workflows/ encontraremos el archivo azure-dev.yaml. Este archivo tendrá el contenido del Worflow de GitHub.
- Este Workflow nos permitirá realizar CI/CD con nuestro Azure Function App utilizando el Public Profile.
- Vale aclarar que existen otros métodos para implementar CI/CD desde GitHub a Azure Functions. Uno de los requisitos de este método es que la Función esté expuesta a internet y tenga habilitado el Public Access.
- En caso de que la Function sea privada y no esté expuesta a internet podemos utilizar otros métodos que exceden el alcance de este post.
- En este archivo yaml (creditos a Azure-Samples) se muestra una alternativa de despliegue a través de un flujo de trabajo que realiza un ‘Az Login’ y lleva a cabo el despliegue en Azure, en lugar de hacerlo directamente en Azure Functions sin la necesidad de conectarse a Azure.”
Obtener el Publish Profile de nuestra Azure Function
Para obtener el Publish Profile de nuestra Function App, debemos:
- Ingresar al portal de Azure.
- Ir a nuestra Function App.
- En la primera pantalla “Overview”, debemos hacer click sobre “Get publish profile”. Esto nos descargará el archivo del publish profile.
- Abrimos el archivo y copiamos el contenido.
Crear Publish Profile secret en GitHub
En una de las actividades finales de esta Demo, generaremos el secret para el publish profile en GitHub actions. Esto nos permitirá que nuestro Workflow, pueda acceder a través de este medio a nuestra Function App. Vale la pena recordar que este método es uno de los utilizados (y uno de los más simples) para realizar CI/CD sobre una function app. Podemos utiilzar otros métodos que, segun el escenario, pueden resultarnos más o menos convenientes.
- Ir a nuestro repo, ingresar a los Settings y hacer click en Secrets and variables>Actions:
- Creamos un nuevo Repository Secret:
- Le daremos el nombre AZURE_FUNCTIONAPP_PUBLISH_PROFILE y en el contenido del secret insertaremos el publish profile obtenido de la function app.
Ejecutar Worflow en GitHub Actions
Ahora ya tenemos configurados todos los parametros de nuestro Worflow. Gracias a el parametro “workflow_dispatch:” tenemos la posibilidad de ejecutar manualmente nuestro Workflow.
- Debemos ingresar al Repo, ir a la solapa de Actions y hacer click en el Workflow (debajo de All workflows en la barra izquierda). Por ultimpo ejecutar “Run Workflow”
- Al ejecutarlo, podemos verificar la el Job en ejecución:
- Ejecución exitosa!
Verificación de deploy en Azure Functions
Podemos verificar en el portal de Azure la correcta implementación:
- Archivos en Azure Functions:
- En los Logs de Deployment Center:
- Vemos nuestra Función dentro de la Function App implementada:
Probar API
Para probar nuestra API implementada en Function App, ingresaremos a nuestra función “http_app_func” desde el Portal:
- Ingresaremos a “Code + Test” y click sobre “Test/Run“:
- Elegiremos los siguientes parametros para el test:
- Método: GET.
- Key: Default (function key)
- *route: /sample:
- Verificamos la respuesta esperada de la App 🙂
- Ahora realizaremos una prueba con la lossiguientes parametros:
- Método: GET.
- Key: Default (function key)
- *route: /hello/{nombre deseado en el output}.
- Vemos el resultado del output:
Leave a Reply