Tuesday, December 10, 2024

A Leap into CDK



A Leap into CDK
by  Maksim Kozyarchuk



Deciding to take the Leap

My relationship with CloudFormation has been a complex one. Most of the time, I’m quite content knowing that my application deployment is fully automated. All I need to do is merge changes into the release branch, and—poof!—a new feature is live in production. However, there are moments when I find myself staring at my sprawling 600+ line template.yml file, feeling overwhelmed by the hidden complexities and creeping inconsistencies.

It was during one of those moments, that I decided to pause the feature I was working on and explore CDK. I had heard about CDK for quite some time, and it felt like the right moment to take the leap.



CDK's Killer Features

CDK's most powerful advantage is its ability to define infrastructure using the full richness of a modern programming language, rather than relying on the static structure of YML. Allowing the following benefits

  • Improved Readability and Organization. With Python, you can organize deployment configurations into modular files, each with clear responsibilities. You can also introduce utilities to enforce custom conventions and defaults, making the setup more consistent and readable.

  • Automated Tests for your Infrastructure. CDK enables you to build unit and regression tests directly on the schema, reducing the risk of unintended changes being deployed.

  • Eliminating Drift Between Mocks and Production.  With CDK, the same resource definitions used for deployment can be leveraged in unit and integration tests, avoiding drift between test mocks and actual production resources—particularly useful for DynamoDB schemas.



A few Observations about CDK

The AWS documentation for CDK is extensive and well worth exploring in depth (AWS CDK Guide). However, as I navigated my way through CDK, a few key insights stood out to me, helping clarify what CDK is—and isn’t.

  • It’s still declarative.   Although CDK uses Python (or another language), it remains declarative.  The primary function of the scripts and stacks you create is to build the full state of your infrastructure.  Equivalent to what would go into a CloudFormation template, then CDK would diff that vs what’s currently deployed and apply the deltas.

  • Independent implementation from SAM. While both CDK and SAM leverage CloudFormation, the way they handle templates and resources appears to differ significantly. This becomes evident when comparing bootstrapping methods for both stacks.  While actual implications of this are not fully clear to me, I would not be surprised to see subtle functional differences.

  • Node.js Dependency.   CDK is implemented in Node.js. If you are using python to define your templates, you’ll need to install Node.js alongside Python in your deployment environments.


My CDK Recipe

Step 1: Configure your project for CDK

  1. Make sure Node.js is installed. If Node.js isn’t installed, get it from Node.js Downloads.

  2. Make sure aws cli is configured

  3. npm install -g aws-cdk  # this installs the cdk globally making it available in path.

  4. Inside your project create cdk subfolder, then run cdk init app --language python inside that

  5. You now have standard project structure with app.py to define the application and a folder for stacks and utilities. The generated README.md provides helpful hints on customizing it further.

Step 2: Define Stacks and Resources

Use app.py to define what stacks you’ll have and their interdependencies.  Define your resources inside the __init__ method of a Stack subclass. There’s no need to return or save anything explicitly—CDK tracks every resource instantiation globally and synthesizes these into a CloudFormation template during the app.synth() step.

Step 3: Deploy via CI/CD

Documentation often calls for running various cdk commands from your local environment, I avoid direct AWS connections from my desktop. Instead, I use GitLab CI/CD pipelines for deployment.

Pipeline Setup
Deploying CDK via GitLab required some effort. The runner needs AWS CLI, Python, and Node.js. Since there are no official Docker images with all three, I started with the public.ecr.aws/sam/build-python3.11 base image and installed the missing dependencies. Here’s the pipeline script:


deploy:

  image: public.ecr.aws/sam/build-python3.11

  script:

    - echo "Running CDK"

    - curl --silent --location https://rpm.nodesource.com/setup_16.x | bash -

    - yum install -y nodejs npm >/dev/null

    - npm install -g aws-cdk >/dev/null

    - cd cdk

    - pip install -r requirements.txt >/dev/null

    - cdk bootstrap aws://$AWS_ACCOUNT/$AWS_REGION

    - export CDK_DEFAULT_ACCOUNT=$AWS_ACCOUNT

    - export CDK_DEFAULT_REGION=$AWS_REGION

    - cdk deploy --require-approval never

    - cd ..

    - echo "CDK Complete"

Note: This setup only works with Node.js 16 due to compatibility issues with Amazon Linux 2.


Final Thoughts

CDK brings powerful capabilities, but it’s not without its quirks. Setting it up, especially for CI/CD, required additional effort compared to YML. However, the benefits of Python's readability, modularity, and integrated testing are promising. As the platform grows, I hope this investment will pay off by simplifying management and reducing errors.

Have you tried CDK? How was your experience, especially with GitLab CI/CD? While CDK was a detour in the journey to turning Kupala-Nich into a platform, it feels like a step in the right direction. Let’s connect and share insights!

No comments: