AWS CDK Version 2. What Is It and Why Should We Care?

AWS CDK Version 2. What Is It and Why Should We Care?

A Brief History of Infrastructure as Code

On AWS re:Invent 2021, the new major CDK version was introduced. There are many great new additions. Let's have a look at what CDK is all about, why we should care, and which new additions were added.

What is AWS CDK?

AWS CDK is the Cloud Development Kit of AWS. It is a framework for building Infrastructure as Code in AWS. The main benefit and difference compared to most frameworks are that you use your own programming language.

AWS CDK uses AWS CloudFormation for provisioning and building cloud infrastructure. Everything which will be supported in CloudFormation is shortly supported in AWS CDK as well. The first programming language AWS CDK is always supporting is TypeScript. All other programming languages are porting into TypeScript and executing that. In the end, always CloudFormation templates will be generated.

What languages are available?

AWS CDK currently offers 5 languages in general availability and one in developer preview.

General Availability:

  • TypeScript
  • JavaScript
  • Python
  • Java
  • C# / .Net

Developer Preview:

  • Go

Constructs, Stacks, and Apps

When working and reading about CDK you often see the terms Constructs, Stacks, and Apps.

constructs stacks and apps

Constructs are the basic cloud components you can use for provisioning infrastructure. This is the basic building block. Constructs are differentiated between L1, L2, and L3 constructs.

  • L1: CloudFormation construct. This is the exact CloudFormation construct
  • L2: L1 constructs with additional defaults and helper methods.
  • L3: L3 constructs are even more abstracted and opinionated. Often they come from community projects.

CDK offers a Construct Library where all constructs are available.

An example L1 construct is this S3 bucket:

new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true
});

Stacks refer to one unit of deployment in AWS CDK. Every building block that gets provisioned is included in this one stack. You can have many (if not unlimited) stacks in your CDK application.

One stack here for example is the provisioning of one S3 bucket. This stack can also include many other constructs.

class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

This brings us to apps. Apps refer to the whole CDK app:

class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");

This should clarify the terminology.

Why use AWS CDK?

Now comes the very important question of why we should use AWS CDK? For that, it is very interesting looking into the history of infrastructure as code.

the history of infrastructure as code

History of IaC

Manual:

Everything started with manual provisioning of cloud resources. You opened the AWS console, launched some services, and let them interact with each other. No history, no governance, no code. When AWS was launching tons of new services and the interaction between all of them became a bit more complex this was just not a feasible approach anymore. Much time now has to be spent documenting how to create a new environment from scratch.

Scripted:

After that many AWS CLI commands and SDKs were introduced. So we could finally use them, develop some scripts to provision everything. SDKs and CLI weren't a perfect approach as well because there was no concrete state and rollback logic. It was more like a workaround to automate some of the manual approaches.

Declarative:

As a third step CloudFormation and Terraform were introduced. This was a real savior and is still one of the most used methods for provisioning cloud infrastructure. Both are great! It is easy to automate the whole process of building whole new environments, everything is reproducible and you have finally a git history.

However, you either need to learn its own syntax or create huge .yaml or .json files the whole day. I don't even start with debugging and testing. So this was not perfect as well.

DOMs:

Document Object Models were already a great step in the right direction. There were a few frameworks like Troposhere that did a great job there. The main difference now was, we can finally write code again. Some of the only bad things were that abstraction was not really built-in so it was hard to share code and these projects were only community-driven so you were dependent on the community to include new services or changes in CloudFormation.

Componentized:

The final stage is where we are today. With CDK you have the benefits of using your own programming language. That means you have all benefits of using code such as abstractions, IDE tools, and familiarity with the syntax. But you also use the powerful provisioning engine CloudFormation. Code generates CloudFormation templates and deploys them to the cloud. If you have certain constructs that need to be enabled multiple times you can build abstractions for that. Another example of a componentized framework is Pullumi, which is basically the CDK for Terraform.

This shows us the history of Infrastructure as Code and gives us the main benefits of why we should use CDK.

Benefits

Developer Experience You are probably a developer who needs to provision code. You are probably familiar with one programming language CDK offers. This is a huge benefit of developer experience compared to learning its own syntax or crunching JSON files all day.

IDE Benefits The great thing that evolved with code is IDEs. IDEs are powerful and developers already know how to handle them and work with them. So you can use your IDE functions for building up your cloud infrastructure. Debugging, refactoring, search + replace are all working as you are used to it.

Abstractions This is more a two-sided sword of AWS CDK. Programming is abstracting. However, abstracting too much doesn't have to be always good. It is great that you can abstract constructs into higher-level constructs and reuse them in several accounts and environments. Just stick to basic programming principles (KISS) for developing your IaC.

Declarative CDK still produces a declarative output. It tells you which resources you want to get and not how to get them. CDK synthesizes your code and tells you if everything is working out well or not.

Stability AWS CDK is a huge project internally of AWS. That means it has the manpower, money, and focus of AWS. During the development of the first version, not everything worked perfectly but it still has one of the best support out there. If a new service launches it will be ported to CDK really fast and this is really important for Infrastructure as Code frameworks.

AWS CDK V2 Additions

Now we understand what AWS CDK is all about. With its new feature Version 2 let's have a look at what changed and what the new things are.

Single package

One of the main differences between AWS CDK Version 2 to AWS CDK Version 1 is that the installation process changed completely. AWS CDK V2 consolidates everything into one package aws-cdk-lib and you don't need to install additional packages. Things like the following snippet are not necessary anymore.

yarn add @aws-cdk
yarn add @aws-cdk/aws-lambda-event-sources
yarn add @aws-cdk/aws-secretsmanager
yarn add @aws-cdk/aws-lambda-nodejs

This is especially helpful because you don't need to synchronize the versions of all different packages you have used and just need to handle one.

Of course, all experimental modules are not included in this package and need to be installed separately. These are especially higher-level constructs (L2 & L3). Experimental packages will still be available for end-users but won't be included in the main package anymore.

CDK Watch

Another new addition is the CLI command cdk watch. Watch lets you watch your code and enables faster inner-loop development. Many web developers know the watch command from npm watch which continuously checks your code and hot-reloads your website in case something changes. cdk watch is almost the same. It allows you to define which changes to watch and which to exclude. It also tries to hot-swap your changes for example by simply switching your lambda code instead of doing a whole CloudFormation deployment. It is a great feature for fast serverless deployment and for faster testing in the cloud but I would hardly recommend using this with caution.

After you initially deployed your cdk stack with cdk deploy you can simply call cdk watch and the watch is running. If a change is detected it looks something like this:

Detected change to 'docker-app/index.html' (type: change). Triggering 'cdk deploy'
⚠️ The --hotswap flag deliberately introduces CloudFormation drift to speed up deployments
⚠️ It should only be used for development - never use it for your production Stacks!

The important part with hotswaps is that redeployments do not necessarily work and you get a drift in your CloudFormation stack. If you don't want to do that use the --no-hotswap flag.

This is a pretty good guide for CDK watch.

Have a look at one example here, I entered cdk watch, editted a lambda function and the deployment starts immediately.

CDK API Reference Improvements

The API reference was updated with a lot more code snippets and additional documentation about the several CDK libraries.

Assertion library for unit tests

CDK V2 also brings a new assertion library to find your errors even before you push your code to the cloud. With this library, you can write even better unit tests.

Further Resources

What is the AWS CDK?

Infrastructure is Code Intro Video

CDK Intro Workshop

Migrating to AWS CDK v2

CDK Watch