Como desplegar una función Lambda con AWS CDK y Typescript

AWS Lambda es una forma muy eficiente de desplegar código y tenerlo funcional en cuestión de minutos. Sin embargo conforme un proyecto se va haciendo cada vez más grande, mantener funciones Lambda de manera manual entrando a la consola de administración es cada vez menos factible.

Imagina que que tienes un montón de funciones todas apuntando a una misma URL o que usan la misma librería y decides cambiar alguna de esas cosas un día. Por cada función que tengas vas a tener que entrar a su sección correspondiente en AWS y actualizar el código.

¿Quién querría perder el tiempo haciendo algo tan trivial? Hay varias formas de solucionar esto en AWS, sin embargo usar el CDK (Cloud Development Kit) te ayudará no sólo con funciones Lambda sino con toda tu infraestructura.

*Si no conoces Lambda puede revisar que es exactamente AWS Lambda o como crear una función Lambda.

Pre-requisitos

Para poder usar el AWS CDK, necesitas lo siguiente:

  1. Llaves de acceso a tu cuenta
    • Access Key ID
    • Secrete Acess Key
  2. Haber configurado tus credenciales para que puedas acceder a AWS con AWS CLI

Instalación Inicial

Para empezar tenemos que correr los siguientes comandos en nuestro CLI.

Lo primero evidentemente será instalar la librería de cdk:

npm install -g aws-cdk

Para probar que la instalación se haya realizado de manera exitosa, solo revisa la versión de tu cdk instalado:

cdk --version

Adicionalmente si no tienes typescript pero aún así te interesa seguir este ejemplo, necesitas instalarlo:

npm install -g typescript

Una vez tengas todo instalado ahora puedes iniciar tu proyecto de cdk en un folder vacío de tu elección:

cdk init app --language typescript

Tu proyecto tendrá una estructura de la siguiente manera:

  • bin
    • cdk-examples.ts
  • lib
    • cdk-examples-stack.ts
  • node_modules
  • test
    • cdk-examples.test.ts
  • .gitignore
  • .npmignore
  • cdk.json
  • jest.config.js
  • package-lock.json
  • package.json
  • README.md
  • tsconfig.json
Captura de pantall que muestra la estrucutra anterior.

Al crear el proyecto se agregaron 2 archivos TS, uno dentro del folder bin y otro dentro del folder lib con el sufijo -stack.

En mi caso los archivos empiezan con ‘cdk-examples‘. Eso depende del nombre de la carpeta en la que hayas inicializado el proyecto.

El archivo en bin es tu archivo principal. Para este ejemplo no lo vamos a modificar pero es en donde puedes indicar si quieres que tu despliegue se haga a alguna cuenta o región en específico en AWS.

Trabajemos sobre el archivo dentro de lib, en mi caso cdk-examples-stack.ts

El archivo generado debe verse algo así.

import * as cdk from '@aws-cdk/core';

export class CdkExamplesStack extends cdk.Stack {
 constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
  super(scope, id, props);
 
  }
}

CDK nos da herramientas para cada servicio que ofrece AWS y para utilizar cada uno necesitas instalar su paquetería correspondiente. En este caso solo necesitamos la paquetería correspondiente a AWS Lambda.

npm install @aws-cdk/aws-lambda

Agrega el import a tu archivo de stack:

import * as cdk from '@aws-cdk/core';
import * as lambda from "@aws-cdk/aws-lambda";

export class CdkExamplesStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
  }
}

Función Lambda

Ahora para empezar necesitamos una función lambda de prueba. La puedes agregar donde quieras. Cabe mencionar que no necesites que tu lambda este en javascript o en typescript, puede estar en cualquier otro lenguaje. (Claro un lenguaje que AWS admita)

En mi caso yo cree estos directorios en el proyecto, junto con un archivo de JS para la lambda.

  • src
    • example-lambda-dir
      • example-lambda.js
Captura de imagen mostrando los folders y archivo anterior.

El archivo de la función lambda es el que se llama example-lambda.js y contiene lo siguiente:

exports.exampleLambda = async (event, context, callback) => {

    return 'Mi primera Lambda desde AWS CDK'
}

Infraestructura de Lambda

Para desplegar la función en AWS necesitas agregar sorprendentemente muy poco código. Al fin y al cabo es como configurar lo que ves en la consola solo que en un lenguaje de programación.

Agrega las siguientes líneas dentro de la clase CdkExamplesStack:

import * as cdk from '@aws-cdk/core';
import * as lambda from "@aws-cdk/aws-lambda";

export class CdkExamplesStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new lambda.Function(this, "lambdaId", {
      runtime: lambda.Runtime.NODEJS_14_X,
      code: lambda.Code.fromAsset("src/example-lambda-dir"),
      handler: "example-lambda.exampleLambda",
    })
    
  }
}

Probablemente ya intuyas que hace cada parámetro pero veamoslo más a detalle de todas maneras.

  • lambdaId – Es el id de la lambda en AWS. Puede ser lo que tu quieras, pero tiene que ser único. Si intentas crear 2 funciones lambda con el mismo id. AWS te dará un error.

  • runtime – Al igual que en la consola de administración, debes de seleccionar en que lenguaje de progamación esta programada tu función lambda.

  • code – Aquí pasas el path hacia la carpeta que contiene tu función lambda. Debe ser hacia una carpeta, porque se pueden desplegar varios archivos hacia una lambda, no necesariamente solo el de la función.

  • handler – el nombre del archivo con la función principal seguida de un punto y del nombre de la función dentro del archivo.

Ahora regresemos a la línea de comandos.

Corre el siguiente comando:

cdk diff --profile default

cdk diff compara lo que tienes en tu máquina local contra lo que hay desplegado en AWS.

*--profile es opcional y sirve para que específiques que perfil y por ende que credenciales de AWS vas a usar para subir la infraestructura. Es útil para cuando estás manejando múltiples cuentas de AWS. Pero si solo tienes una no es necesario.

Dado que es la primera vez que estás desplegando la función AWS debe mostrarte algo similar a esto:

Captura de imagen mostrando los resultados de despliegue exitosos dentro de la terminal de comandos.

Es buena idea que cada vez que le hagas un cambio a la configuración corras este comando, ya que te ayudará a visualizar que esta detectando AWS CDK y qué no.

*Por cierto si cdk diff no te da el resultado que esperabas, tal vez sea porque te hace falta llamar el siguiente comando antes.

cdk bootstrap

Es un comando de preparación y ayuda a conectar tu cuenta con el proceso de AWS CDK. Si tuviste problemas para correr cdk diff, intenta con este último comando y vuelvelo a llamar.

Ya que revisaste que todo esta en orden solo necesitas el siguiente comando para subir tu archivo a AWS.

cdk deploy --profile default

Para temas de permisos AWS siempre requerira tu confirmación. Como todas las lambdas requieren que se les asigne por default un rol de ejecución, AWS lo toma como modificaciones relacionadas a seguridad.

Captura de imagen mostrando en la terminal como se detectan los cambios relaciones a roles de la lambda y preguntando si deseas desplegarlos.

Una vez hayas aceptado, la ejecución se tardará entre 1 y 2 minutos y verás esto como resultado

Captura de imagen mostrando en la terminal el resultado exitoso de la actualización.

Tu función ya esta en al nube!

Vamos a comprobarlo.

Al acceder a tu cuenta de AWS abre 2 secciones: Lambda y CloudFormation

Captura de pantalla de AWS remarcando los servicios de CloudFormation y Lambda visibles desde el Dashboard principal.

Dentro de Lambda deberías ver tu función creada

Captura del panel de AWS Lambda mostrando la función creada a través de la terminal.

Dado que no le pusimos un nombre explicítamente, AWS le asigna un nombre que se compone del nombre del stack, y del id que le dimos.

Al entrar ya podemos ver nuestro código en el editor en línea. (Recuerda que el editor no esta disponible para todos los lenguajes)

Captura de la sección de Código Fuente de la lambda creada a través de la terminal mostrando que el código es el mismo que se tenía en la función.

Si probamos la llamada nos regresa el resultado que esperamos

Captura de pantalla mostrando una ejecución exitosa de la función lambda a través de la interfaz de AWS.

Ahora vamos a la sección de CloudFormation. Aquí debes encontrar un stack o pila con el nombre correspondiente.

Captura de pantalla del panel de CloudFormation en AWS mostrando las pilas/stacks creados.

Si no sabes qué es CloudFormation te explicó rápidamente.

CloudFormation es un servicio de AWS para desplegar infraestructura a través de un template en formato json o yml. Estos archivos permiten especificar que servicios vas a desplegar así como sus características, conexiones, permisos, etc. Cumple la misma función que AWS CDK.

¿Pero porqué tenemos que entrar a la sección de CloudFormation si lo que usamos fue el CDK? Simple, el CDK detrás de cámaras utiliza templates de CloudFormation. Cuando tu compilas el código, AWS CDK lo transforma a un template válido de CloudFormation y lo sube así.

No necesitas saber mucho en específico de CloudFormation, solo debes tener claro el concepto de stacks. Para ello te recomiendo que le heches una leída aquí.

Actualizar tu lambda ahora es trivial, haz los cambios que quieras y corre el comando de deploy cuando estes listo.

Por último. ¿Qué hacemos si queremos borrar lo que subimos? Aquí entra el último comando que debes aprender.

cdk destroy --profile default

Este comando como su nombre lo indica se encargará de destruir todo lo que hayas subido en este stack. Evidentemente debes tener mucho cuidado cuando mandes a llamar este comando. El cuál te debe regresar este resultado:

Captura de pantalla de la termial mostrando el resultado exitoso de haber borrado todo lo que se subió en el stack.

Listo! ahora tienes un proyecto funcional que te sirve para subir tus funciones lambda! Puedes aprovechar todas las bondades del código para compartir variables, usar condiciones, usar ciclos, etc. Y no solo sirve para Lambda, si necesitas desplegar algun otro servicio también puedes hacerlo con CDK. Visita su API si quieres saber más.