Hoy en día estamos inmersos en la tendencia de que muchas empresas están desarrollando aplicaciones Cloud Native o migrando sus aplicaciones On-Premise a la nube. Dichas aplicaciones necesitan disponer de la infraestructura necesaria para su puesta en marcha, la cual debe ser consistente, de tal manera que se pueda desplegar de manera repetible en todos los entornos. Para ello, el concepto de IaC (Infrastructure as Code) ha irrumpido en el mundo del desarrollo de aplicaciones en la nube, permitiendo crear la infraestructura de las mismas mediante código.

Los principales proveedores de la nube (AWS, Azure y GCP) tienen su propio servicio para implementar y desplegar la infraestructura como código usando plantillas en formato JSON o YAML, donde podemos encontrar el servicio CloudFormation en AWS, Resource Manager en Azure y Cloud Deployment Manager en GCP.

También existe la posibilidad de emplear herramientas multi-cloud como Terraform que permite desplegar infraestructura en cualquiera de las nubes más populares utilizando una misma notación mediante el lenguaje (HCL) y que se explica en detalle en este otro post. Por último, y como veremos a lo largo de este post, también podemos implementar y desplegar IaC de la misma forma en la que desarrollamos una aplicación con Python. Si quieres profundizar en qué consiste la IaC, en este interesante post puedes hacerlo.

En este post vamos a centrarnos en explicar el funcionamiento del Cloud Development Kit (CDK Version 2) que ofrece AWS para implementar y desplegar IaC y, además, veremos un ejemplo práctico de definición y despliegue de un caso de uso básico usando el lenguaje Python.

¿Qué es el CDK?

Para entender qué es CDK, primero vamos a explicar brevemente qué es CloudFormation.

CloudFormation es un servicio de AWS que permite definir IaC compuesta por diversos recursos de AWS, de manera declarativa usando templates JSON o YAML, de tal manera, que la IaC sea consistente, repetible y auditable a medida que se vaya desplegando en diversos entornos.

CDK es un framework que permite definir IaC y desplegarla en AWS mediante CloudFormation de manera imperativa, es decir, mediante un lenguaje de programación, sin necesidad de emplear templates. En su lugar, como he mencionado antes, se usa código en lenguajes como Python, TypeScript (el core de CDK está desarrollado en este lenguaje), JavaScript, Java, C#, o Go, con todas las ventajas que ello conlleva.

Por ejemplo, puedes desplegar IaC con base en condiciones if...else, usar loops, crear librerías, modularizar y en definitiva usar todo lo que nos ofrecen los lenguajes de programación.

CDK no pretende sustituir a CloudFormation, por el contrario, se sustenta en dicho servicio. CDK se puede usar para casos de uso en los que la IaC se puede definir de manera imperativa, es decir, que mediante el uso de un lenguaje de programación especificamos como queremos desplegar la IaC de manera dinámica, mientras que CloudFormation se puede usar cuando la IaC se defina de manera declarativa y un poco más rígida, de tal manera que mediante una template en JSON o YAML especificamos cúal es el estado final deseado una vez la IaC sea desplegada.

Sin embargo, CDK “behind the scenes” genera plantilla de CloudFormation, por tanto, aunque CDK sea una herramienta que usa lenguajes imperativos, también ofrece las ventajas de definir IaC de manera declarativa, la cual conoce el estado actual de la IaC permitiendo identificar las diferencias automáticamente y solo modificar aquello que ha cambiado.

Puede parecer un poco confusa la diferenciación entre imperativo y declarativo a la hora de implementar IaC. Te dejo este enlace muy interesante donde lo explican más en detalle identificando las ventajas y desventajas de cada planteamiento, y este otro enlace donde lo explican partiendo de un ejemplo de IaC con CDK.

CDK v1 vs. CDK v2

Comparando CDK v2.x respecto a su predecesora CDK v1.x, la versión que explicamos ofrece más estabilidad en cuanto a que se añaden componentes estables, los experimentales se identifican fácilmente, ya que llevan el sufijo alfa o beta (p.e. aws_cdk.aws_batch_alpha), cosa que no sucede en la v1.x, donde esa diferenciación entre lo estable y experimental no es tan evidente, a menos que vayas a la documentación.

Por tanto, es más sencillo hacer un upgrade de por ejemplo la versión 2.17.1 a la versión 2.28.1 por ejemplo. Esto último en la v1.x es más difícil, ya que para realizar un upgrade de la versión 1.44 a la versión 1.160.0, nos vamos a encontrar que muchos métodos usados en la versión antigua están obsoletos en la versión más reciente, en consecuencia se debe hacer un refactor.

Además, en la v2.x todos los Constructs, que veremos más adelante, están empaquetados en solo 2 librerías. Por otra parte, en la v1.x se deben importar de manera independiente cada uno de los Constructs que queremos emplear en la IaC, como se muestra en la siguiente tabla comparativa, donde se detallan los módulos que se deben incluir en el requirement.txt en función de si utilizamos la versión 1.x o 2.x del CDK.

requirements.txt en CDK v1.x requirements.txt en CDK v2.x
aws-cdk.core == 1.44.0 aws-cdk-lib==2.3.0
aws-cdk.aws-s3 == 1.44.0 constructs>=10.0.0,<11.0.0
aws-cdk.aws-lambda == 1.44.0
aws-cdk.aws-stepfunctions == 1.44.0
aws-cdk.aws-stepfunctions-tasks == 1.44.0
aws-cdk.aws-ecr == 1.44.0
aws-cdk.aws-ec2 == 1.44.0
aws-cdk.aws-iam == 1.44.0

Si has trabajado con CDK v1.x y quieres ver qué cosas cambian respecto a la v2.x, este enlace te vendrá genial para identificar las diferencias entre ambas versiones.

¿Qué ventajas ofrece el CDK?

El uso del CDK permite gestionar la IaC como si de una aplicación se tratase, permitiendo agrupar la IaC en módulos, usar objetos, crear librerías para su uso en múltiples aplicaciones, hacer pruebas unitarias, versionar, etc.

CDK al ser una herramienta que usa lenguajes imperativos, además de las ventajas indicadas anteriormente, te permite definir IaC de manera dinámica y más accesible a los desarrolladores que no estén familiarizados con notaciones como JSON o YAML.

Como desventaja podríamos destacar que en ocasiones nos podemos ver en la situación de querer configurar un recurso de AWS en la IaC y ver que el CDK no provee una clase o método para hacerlo o que presentan fallos, mientras que si lo hiciésemos con CloudFormation no habría problema. Para mitigar esto, CDK libera una release cada semana donde se añaden correcciones o cubren nuevas funcionalidades. Al final, CDK no deja de ser un modo de abstracción de CloudFormation, por tanto, va un paso por detrás.

Si estás familiarizado con los lenguajes de programación que soporta el CDK, indicados anteriormente, te resultará menos difícil adaptarte a su uso para implementar la IaC de tu aplicación.

En lugar de tener una template de CloudFormation en YAML o JSON de centenares de líneas, con sus parámetros, condiciones, variables, etc., que puede hacerse inmanejable o difícil de entender, mediante el CDK puedes simplificar esa ingente cantidad de líneas en muchas menos y tener una IaC más estructurada y legible.

Componentes del CDK

Como todo framework que se respete, CDK está compuesto por diversos elementos que se pueden ver en la siguiente imagen: App, Stack, Construct y que explicamos a continuación.

Componentes del CDK. Fuente: docs.aws.amazon.com
Componentes del CDK. Fuente: docs.aws.amazon.com

App

La CDK App es el conjunto de stacks que conforman la IaC que se quiere desplegar en AWS. Como buena práctica conviene tener varias stacks para definir y desplegar recursos de diferente naturaleza como por ejemplo una stack para recursos de red (p.e. VPC, Subnets, etc.), otra stack para los recursos de almacenamiento (S3, DynamoDB, etc.), otra para los recursos de cómputo (p.e. clúster de EMR), seguridad (p.e. Roles, KMS, etc.) y así con el resto de servicios que ofrece AWS.

Stack

Una stack es un conjunto de recursos (Construct) que se quieren desplegar en AWS. Una Stack de CDK representa a una stack de CloudFormation que es, a fin de cuentas, lo que genera el CDK y que veremos posteriormente en el caso práctico.

Construct

Un Construct es la representación de un recurso de AWS, como por ejemplo un bucket de S3, un rol de IAM, una step function, una instancia EC2, etc. Los Constructs se agrupan en stacks y son equivalentes a los tipos existentes en CloudFormation como por ejemplo: AWS::S3::Bucket, AWS::IAM::Role, AWS::EC2::Instance, etc.

CDK usa la librería AWS Constructs Library que ofrece un conjunto de Construct para cada uno de los servicios que podemos encontrar en AWS. Puedes acceder al Construct Hub para descubrir los Constructs existentes de AWS.

También puedes crear tu propio Construct, de tal manera que puedas desplegar un componente de AWS customizado que cumpla ciertos criterios de seguridad o de cualquier otra índole y luego compartirlo en algún repositorio de artefactos para que la IaC de otras aplicaciones puedan utilizarlo.

Como buena práctica, al implementar un Construct conviene tener en mente su reusabilidad, ya que seguramente puedas necesitarlo en la IaC de otra aplicación.

Para obtener más información acerca de los Construct puedes acceder a la documentación oficial de AWS.

Manos a la obra

Teniendo claro lo que es el CDK y cuáles son sus componentes, vamos a implementar un caso de uso básico que consiste en generar la IaC para desplegar y ejecutar una step function que invoca a 2 lambdas y que luego envía una notificación a los suscriptores de un tópico SNS.

La step function se ejecutará automáticamente al subir un fichero a un bucket de S3 usando una regla de Event Bridge. A continuación, puedes ver un diagrama con los servicios de AWS que serán empleados en la generación de la IaC y cómo interactúan entre sí.

Recursos AWS que componen la IaC del caso de uso.
Recursos AWS que componen la IaC del caso de uso.

El objetivo de este caso de uso práctico es solo ejemplificar cómo se genera la IaC con CDK, por ello el código que se ejecuta en las lambdas no es relevante.

Para ver el funcionamiento del CDK y generar la IaC de este caso de uso vamos a seguir los pasos que se detallan a continuación.

Instalación del CDK

Antes de poder usar el CDK con Python debemos cumplir con algunos prerequisitos. Por ejemplo, tener instalado Node.js, ya que como mencionamos anteriormente, el core del CDK está implementado en lenguaje TypeScript. Durante la redacción de este post, la versión más estable de Node.js testeada para CDK es la v16.15.1. Para instalar Node.js y npm de acuerdo a tu sistema operativo puedes acceder a este enlace.

Otro prerrequisito que necesitas cumplir es el de tener instalado en tu ordenador el AWS CLI. Una vez instalado, ejecutar el comando aws configure para generar las credenciales que le permitirán al CDK interactuar con los servicios de AWS como CloudFormation, que a fin de cuentas es el encargado de desplegar los recursos definidos en la IaC implementada con CDK.

Una vez instalados los prerequisitos descritos anteriormente, puedes proceder a instalar el CDK mediante el gestor de paquetes de Node.js, npm, ejecutando el siguiente comando:

npm install -g aws-cdk

Para verificar la instalación del CDK puedes ejecutar el siguiente comando:

cdk --version

La última versión del CDK a fecha de elaboración de este post es la 2.28.1. Puedes consultar la documentación de la API de Python del CDK en este enlace, o en su defecto ejecutar el comando cdk docs, que automáticamente te llevará a la documentación de la versión del CDK que hayas instalado. También puedes descargar la documentación de una versión específica del CDK en GitHub.

Para más detalles sobre el proceso de instalación del CDK puedes consultar este enlace.

Crear aplicación con CDK

Una vez tenemos instalado el CDK, el siguiente paso es crear una aplicación donde definiremos la IaC que queremos desplegar en AWS. El primer paso es crear un directorio, al que llamaremos poc-cdk-v2, donde vamos a crear nuestra aplicación.

mkdir poc-cdk-v2 && cd poc-cdk-v2

El siguiente paso, ejecutar el comando del CDK para crear la aplicación dentro de la cual vamos a definir la IaC con Python.

cdk init app --language python

Después de ejecutar el comando anterior, el CDK genera los siguientes directorios y ficheros dentro del directorio poc-cdk-v2. Cómo podéis ver, por defecto se produce un virtual environment, que en Python es imprescindible para evitar conflictos con librerías de otras aplicaciones que estemos desarrollando.

Estructura de directorios y ficheros generados por CDK por defecto.
Estructura de directorios y ficheros generados por CDK por defecto.

Los ficheros más importantes que debes conocer son los siguientes:

#!/usr/bin/env python3
import aws_cdk as cdk

from poc_cdk_v2.poc_cdk_v2_stack import PocCdkV2Stack

app = cdk.App()
PocCdkV2Stack(app, "PocCdkV2Stack")

app.synth()
from aws_cdk import (
    core as cdk,
    aws_sqs as sqs,
)
from aws_cdk import core

class PocCdkV2Stack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        # The code that defines your stack goes here
        # example resource
        queue = sqs.Queue(
            self, "PocCdkV2Queue",
            visibility_timeout=cdk.Duration.seconds(300),
        )
aws-cdk-lib==2.3.0
constructs>=10.0.0,<11.0.0

A continuación, activamos el virtual environment de Python.

source .venv/bin/activate

Instalamos los módulos que se encuentran en el fichero requirements.txt.

pip install -r requirements.txt

Al tener instalado CDK en nuestro entorno de desarrollo ya tenemos todo lo necesario para empezar con la parte más interesante, ver al CDK en acción. Para ello, borramos el código generado por defecto en el fichero poc_cdk_v2_stack.py y añadimos en primera medida los import de los diferentes recursos que componen nuestra IaC y que ya hemos visto previamente en el diagrama del caso de uso.

from aws_cdk import (
    Stack,
    aws_stepfunctions as step_functions,
    aws_stepfunctions_tasks as tasks,
    aws_events as events,
    aws_events_targets as targets,
    aws_iam as iam,
    aws_lambda as lambda_,
    aws_sns as sns,
    aws_s3 as s3
)

from constructs import Construct

CDK permite que podamos crear Construct customizados. Para ello solo basta producir una clase que herede de Construct y que tenga un método init. Para este caso de uso práctico vamos a crear 3 Construct customizados que se detallan a continuación:

El primer Construct es para crear un estado inicial Pass en la step function y, al que se le añadirán más pasos posteriormente para invocar a las lambdas y enviar notificación SNS.

class StartProcess(Construct):
    """
    Custom construct to set initial Pass state into step function.
    """
    def __init__(self, parent: Construct, id: str, **kwargs) -> None:
        """
        Creates a new construct node.

        :param parent: The scope in which to define this construct.
        :param id: The scoped construct ID. Must be unique amongst siblings. 
        """
        super().__init__(parent, id)

        self.sfn = step_functions.Pass(
            self, "Start Process"
        )

El segundo Construct es para crear las 2 lambdas que serán invocadas desde la step function y que recibe cómo parámetros (mediante el parámetro **kwargs), el nombre de la lambda y el path local donde se encuentra el código python de cada lambda, por ello se puede reutilizar para crear varias lambdas.

class InvokeLambda(Construct):
    """
    Custom construct to create a lambda function and invoke it from step function.
    """
    def __init__(self, parent: Construct, id: str, **kwargs) -> None:
        """
        Creates a new construct node.

        :param parent: The scope in which to define this construct.
        :param id: The scoped construct ID. Must be unique amongst siblings. 
        """
        super().__init__(parent, id)

        lambda_name = kwargs.get("lambda_name")
        path_lambda_src = kwargs.get("path_lambda_src")

        lambda_function = lambda_.Function(
            self, f"cdk_{lambda_name}",
            function_name = lambda_name,
            runtime = lambda_.Runtime.PYTHON_3_8,
            code = lambda_.Code.from_asset(path_lambda_src),
            handler = 'lambda_function.lambda_handler',
            role = iam.Role(
                self, f"cdk_role_{lambda_name}",
                assumed_by = iam.ServicePrincipal("lambda.amazonaws.com"),
                inline_policies = {
                    f"cdk_role_policy_{lambda_name}": 
                    iam.PolicyDocument(
                        statements = [
                            iam.PolicyStatement(
                                actions = ["s3:*"],
                                effect = iam.Effect.ALLOW,
                                resources = ["*"]
                            )
                        ]
                    )
                },
                role_name=f"role_{lambda_name}"
            )
        )

        """
        Add created lambda as a step function task.
        """
        self.task = tasks.LambdaInvoke(
            self, f"Invoke {lambda_name}",
            lambda_function = lambda_function,
            result_path = f"$.result_{lambda_name}"
        )

El tercer Construct es para crear un tópico SNS y enviar notificación a los suscriptores del mismo.

class PublishSNS(Construct):
    """
    Custom construct to create a SNS topic and publish notification from step function.
    """
    def __init__(self, parent: Construct, id: str, **kwargs) -> None:
        """
        Creates a new construct node.
        :param parent: The scope in which to define this construct.
        :param id: The scoped construct ID. Must be unique amongst siblings. 
        """
        super().__init__(parent, id)
        sns_topic = sns.Topic(
            self, "cdk_sns_topic", topic_name = "NotifyResults"
        )
        """
        Add SNS notification as a step function task.
        """
        self.task = tasks.SnsPublish(
            self, "Publish Notification",
            topic = sns_topic,
            subject = "Results",
            message = step_functions.TaskInput.from_json_path_at(
                "$.result_LambdaTwo.Payload.message"
            )
        )

A continuación, creamos la clase principal donde se implementará la IaC, la cual debe heredar de Stack y además debe tener definido el método init como se muestra:

class PocCdkV2Stack(Stack):
    """
    Principal class to define IaC Stack with resources to deploy. 
    """
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        """
        Creates a new stack.

        :param scope: Parent of this stack, usually an App or a Stage, but could be any 
                      construct.
        :param construct_id: The construct ID of this stack. If stackName is not 
                             explicitly defined, this id (and any parent IDs) will be
                             used to determine the physical ID of the stack.
        """
        super().__init__(scope, construct_id, **kwargs)

Dentro del método init añadimos el código CDK para crear todos los recursos que deseamos desplegar.

En primer lugar, creamos un bucket de S3, en cuya configuración activamos las notificaciones de Event Bridge, de tal manera que posteriormente podamos elaborar una regla que inicie la ejecución automática de la step function como respuesta a un evento que se genere en dicho bucket, por ejemplo cada vez que se suba un fichero.

"""
Create S3 Bucket through CDK native s3.CfnBucket Construct.
"""
s3.CfnBucket(
    self, "cdk_bucket_input", 
    bucket_name="s3-input-bucket-poc-cdk",
    notification_configuration=s3.CfnBucket.NotificationConfigurationProperty(
        event_bridge_configuration=s3.CfnBucket.EventBridgeConfigurationProperty(
            event_bridge_enabled=True
        )
    )
)

Ahora generamos la step function que se encargará de crear e invocar a 2 lambdas y publicar una notificación a un tópico de SNS.

Como veréis en el siguiente código se usan Construct nativos de CDK como: iam.Role, iam.PolicyDocument y step_functions.StateMachine y también se usan Construct customizados definidos anteriormente: InvokeLambda y PublishSNS.

"""
Create Step Function definition with initial step through custom Construct.
"""
step_function_definition = StartProcess(self, "Start process").sfn

"""
Create Step Function role and its policy with permissions.
"""
sfn_role = iam.Role(
    self, "cdk_role_step_function",
    assumed_by = iam.ServicePrincipal("states.amazonaws.com"),
    inline_policies = {
        "cdk_role_step_function_policy": 
            iam.PolicyDocument(
                statements = [
                    iam.PolicyStatement(
                        actions = ["s3:GetObject",
                                   "sns:Publish",
                                   "lambda:InvokeFunction"],
                        effect = iam.Effect.ALLOW,
                        resources = ["*"]
                    )
                ]
            )
    },
    role_name = "role_step_function"
)

"""
Create Step Function to orchestrate Lambdas and SNS notification, using InvokeLambda
and PublishSNS custom constructs.
"""
step_function_cdk = step_functions.StateMachine(
    self, "cdk_step_function",
    role = sfn_role,
    state_machine_name = "step_function_orchestration",
    definition = step_function_definition.next(
        InvokeLambda(
            self, "cdk_lambda_one", 
            lambda_name = "LambdaOne",
            path_lambda_src = "./lambdas/Lambda_one"    
        ).task
    ).next(
        InvokeLambda(
            self, "cdk_lambda_two", 
            lambda_name = "LambdaTwo",
            path_lambda_src = "./lambdas/Lambda_two"
        ).task
   ).next(
       PublishSNS(self, "Notify Lambda Results").task
   )
)

"""
Add dependency between step function and role similar to DependsOn attribute in CloudFormation.
"""
step_function_cdk.node.add_dependency(sfn_role)

Creamos la regla de Event Bridge para ejecutar automáticamente la step function cuando un fichero es creado en el bucket de S3.

"""
Define Event Rule to specify which S3 event could trigger a Step Function.
"""
event_rule = events.Rule(
    self, "cdk_event_rule", 
    event_pattern=events.EventPattern(
        source=["aws.s3"],
        detail_type=["Object Created"]
    )
)
"""
Add rule's target to trigger Step Function when the event pattern occurs.
"""
event_rule.add_target(
    targets.SfnStateMachine(
        step_function_cdk
    )
)

Desplegar aplicación con CDK

Una vez tenemos implementada la IaC podemos proceder a su despliegue en AWS. Para ello CDK proporciona varios comandos para este cometido y que explicamos a continuación.

CDK synth

El primer comando que debemos ejecutar es cdk synth, usando la opción --profile en caso que tengas más de una cuenta de AWS en tu fichero .aws/credentials. La salida de este comando es la que podemos ver en la siguiente imagen:

Salida del comando cdk synth.
Salida del comando cdk synth.

Básicamente, lo que hace el comando cdk synth es generar una plantilla de CloudFormation en formato YAML, donde se describen los recursos incluidos en la stack que hemos implementado en CDK.

CDK bootstrap

Si tenemos assets en nuestro entorno local, como por ejemplo ficheros python con el código de las lambdas, debemos ejecutar el comando cdk bootstrap, el cual se encarga de crear un bucket de S3 para guardar los assets. De hecho, durante la ejecución de este comando, se genera una stack en CloudFormation llamada CDKToolkit cuyos recursos son el bucket de S3, además de varios roles y permisos.

Salida del comando cdk bootstrap.
Salida del comando cdk bootstrap.

CDK deploy

Ahora, para desplegar la IaC ejecutamos el comando cdk deploy, el cual produce una stack en CloudFormation con todos los recursos definidos en la Stack del fichero poc_cdk_stack.py, que hemos detallado anteriormente y además nos muestra los recursos que se van a originar.

Al confirmar que deseamos desplegar los recursos listados en la imagen anterior, se crea una Stack en CloudFormation donde se despliegan todos los recursos de la IaC.

Stack de CloudFormation con recursos de IaC generada con CDK.
Stack de CloudFormation con recursos de IaC generada con CDK.

Para comprobar que la IaC desplegada funciona correctamente, vamos a insertar un fichero en el bucket de S3 y acto seguido veremos que la step function se ejecuta automáticamente.

Subir fichero al bucket para ejecutar regla de Event Bridge.
Subir fichero al bucket para ejecutar regla de Event Bridge.

La regla de Event Bridge creada en la IaC ejecuta automáticamente la step function que realiza la ejecución de las 2 lambdas y envía una notificación al tópico SNS.

Ejecución satisfactoria de Step function implementada en CDK.
Ejecución satisfactoria de Step function implementada en CDK.

Cuando modificamos alguno de los recursos que conforman la IaC, por ejemplo, si insertamos un nuevo paso de tipo Wait, entre las invocaciones de las lambdas, modificando el código que crea la step function, como se muestra a continuación:

step_function_cdk = step_functions.StateMachine(
            self, "cdk_step_function",
            role = sfn_role,
            state_machine_name = "step_function_orchestration",
            definition = step_function_definition.next(
                InvokeLambda(
                    self, "cdk_lambda_one", 
                    lambda_name = "LambdaOne",
                    path_lambda_src = "./lambdas/Lambda_one"    
                ).task
            ).next(
                step_functions.Wait(self, "Wait X Seconds",
                    time=step_functions.WaitTime.duration(Duration.seconds(5))
                )
            ).next(
                InvokeLambda(
                    self, "cdk_lambda_two", 
                    lambda_name = "LambdaTwo",
                    path_lambda_src = "./lambdas/Lambda_two"
                ).task
            ).next(
                PublishSNS(self, "Notify Lambda Results").task
            )
        )

Podemos ejecutar el comando cdk diff para ver las diferencias entre lo que está desplegado respecto a lo que tenemos en nuestro entorno local sin desplegar. Al ejecutar dicho comando, CDK nos muestra las diferencias encontradas, en este caso nos muestra las diferencias en la definición de la step function.

Esta es una de las ventajas de que CDK genere por detrás una template de CloudFormation para identificar las diferencias automáticamente.

Salida del comando cdk diff.
Salida del comando cdk diff.

Después de desplegar los cambios, la step function se actualiza con el nuevo paso Wait añadido previamente.

Step function con el nuevo paso Wait X Seconds.
Step function con el nuevo paso Wait X Seconds.

Si modificamos los permisos del rol de la step function para añadir la acción “S3:PutObject”, al ejecutar el comando cdk deploy, podemos visualizar fácilmente los cambios que tendrán lugar en la IaC antes de confirmarlos.

CDK destroy

Para eliminar la stack de antes ejecutamos el comando cdk destroy.

Además de los comandos CDK que hemos usado anteriormente, existen otros que conviene conocer: cdk diff y cdk doctor. El primero, como hemos visto, se usa para ver las diferencias entre la stack de tu entorno de desarrollo respecto a lo que ya está desplegado en AWS y el segundo es para identificar posibles problemas en la stack. Para ver más detalles sobre estos y todos los comandos que ofrece CDK puedes consultar este enlace.

La stack generada por el comando cdk bootstrap, CDKToolkit, se debe eliminar manualmente desde la consola.

Conclusiones

CDK es una herramienta que nos permite desplegar IaC de una manera similar a la construcción del backend de una aplicación, por ello los desarrolladores podemos sentirnos más cómodos con esta forma de desplegar recursos en AWS con Python u otro lenguaje imperativo soportado por CDK.

La documentación del API del CDK es muy extensa para todos los lenguajes de programación soportados, en especial para TypeScript, y no resultará difícil implementar la IaC que use los diversos servicios que ofrece AWS.

Cómo todo framework, CDK tiene una serie de buenas prácticas que puedes aprender a implantar en la IaC de tu aplicación y que encontrarás en este enlace.

CDK es un framework en constante evolución, cada poco tiempo se libera una nueva release con mejoras o bug fixes.

Una característica interesante del CDK, y que merece un post completo, es la capacidad de implementar test unitarios de la IaC mediante Pytest. Puedes ver ejemplos de test unitarios de CDK en este enlace o en este otro.

En este enlace tienes acceso al roadmap del CDK, repositorios con ejemplos, workshops, blogs y charlas técnicas sobre el CDK.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.