AWS CDK - First impression last

2019-08-14

A couple of weeks ago I decided to give the AWS CDK (Cloud Development Kit) a go. It had just become general available and the support for Python was in place.

Even though the CDK was introduced already at Re:Invent 2018 I had not looked in it's direction. Mainly due to the fact that I really like CloudFormation, I have some templates I reuse over and over again, and of course the lack of Python support.

But after the GA announcement I felt that it was time to check it out, and you know what..... First impressions do last.

In this post I will go through my thought regarding things like installations, setup, to creating my first app.

What is it, and how does it work?

Most of you are probably familiar with the concept of infrastructure as code. It's a great benefit to be able to create and recreate an environment over and over again in the exact same way.
My preferred way to model my infrastructure in AWS has been to use CloudFormation. Sure there are other tools like Terraform, Troposphere, and more. But CloudFormation still remained my favorite.

The CDK is an other tool to to model you infrastructure in AWS. The core building block in the CDK is the Construct which I would say is a collection of cloud resources. It can be as simple as a S3 bucket but it can also represent a very complex architecure with ECS clusters, load balancers, EC2 instances, and more. A Construct can also contain other constructs, which makes thing much easier to reuse.
Constructs are the grouped together into Stack(s) which you then can deploy into your environment. Stacks are the grouped together in an App. A picture probably explains it better.

image{:class="img-responsive"}

The concept around apps, stacks, and constructs feels really appealing to me. I like that I basically can create constructs that then can be reused in stacks and apps over and over again. With stacks we can create an app with one stack per region and environment and deploy them individually, I like that.

Installation, setup, and use

First of all we need to install the CDK it self. The CDK is written in Node.Js so we need to have Node.Js 8.1.1 or higher already installed. I already had that installed so I will just assume the same thing goes for you. To install the CDK just run:

npm install -g aws-cdk

Then check the installed version with:

cdk --version

So far so good, what do we more need to do? Well CDK rely on AWS credentials for deploying our apps. We can either use --profile option to each CDK command to specify the named profile to use, or if we have a default profile setup the CDK will use just that one. In this test I did rely on the default profile in my AWS credentials settings. If you for some reason don't have any credentials check the documentation.

The installation was really easy and straight forward. I didn't run into any problems at all.

My first creation

I decided that would build something, that I must have built a hundred times before. A simple VPC with 2 public, 2 private subnets, a Nat gateway in one of the public subnets, and then some routing tables.

So first let's create the application. To init a new application you just have to run the init command.

cdk init --language LANGUAGE

So in my case of using python I just run

cdk init --language python

The init worked like a charm and all basic files and folders was in place. Since this was a python based app we should be running in a virtual environment, the documentation states that this should be taken care of by the init. Well for me it didn't, I hade to create it my self and start it. Not that big of a deal maybe but you will se further ahead that there is more incorrect or unclear documentation.

Anyhow, to create the virtual environment and start it navigate to your app root folder and run

python3 -m venv .env
source .env/bin/activate

Now when the virtual environment was finally running it's time to install the dependencies. The init command created the requirements.txt file. This example requires aws-cdk.core version 1.3.0 or higher. So if you are following along make sure you have this line in your file

aws-cdk.core>=1.3.0

Then we run

pip install -r requirements.txt

So far so good, I was really happy with the experience, smooth with just a few small bumps. What is important to remember is that the CDK is divided into smaller pieces, so you will not get everything you need from the core part. As example there is aws-cdk.aws-s3 and aws-cdk.aws-lambda and more. So make sure you install the things you need.

Time to start building then. I decided to start small and just followed a simple example to create a standard basic VPC. Which is amazingly simple.


from aws_cdk import (
aws_ec2 as ec2,
core,
)

app = core.App()
stack = core.Stack(app, "simple-vpc-stack")

vpc = ec2.Vpc(
stack, "MyVpc",
max_azs=2
)

app.synth()

That's it... That will generate a pretty large CloudFormation template that will create a 2 AZ VPC. Pretty impressive I must say.
But.... It doesn't create the setup I like, it creates two NAT Gateways. Yes that might be best practice from a redundancy point of view, but this test is not about that. Also it doesn't create the CIDR ranges I like so we need to modify it a bit.

It was now my headache started, because if I look in the documentation for python the example AWS provides is for Javascript and not for Python. Well, not a huge problem I realized that something was wrong when comparing the documentation and the python docs.

So let us now update the app to specify cidr, subnets, and nat gateways.


from aws_cdk import (
aws_ec2 as ec2,
core,
)


app = core.App()
stack = core.Stack(app, "simple-vpc-stack")


vpc = ec2.Vpc(
stack, "MyVpc",
cidr="10.125.0.0/16",
max_azs=2,
nat_gateways=1,
subnet_configuration=[
ec2.SubnetConfiguration(
name="public", cidr_mask=24, subnet_type=ec2.SubnetType.PUBLIC),
ec2.SubnetConfiguration(
name="private", cidr_mask=24, subnet_type=ec2.SubnetType.PRIVATE)

]
)

app.synth()

Perfect, that generated exactly what I wanted. I'm happy. With only these few lines of code I get a huge CloudFormation template. I really like this! So much boiler plate code that I now don't have to write anymore. But wait..... There is one thing missing. Tags, I like to assign tags that can be used for cost allocation to all resources, normally that is a lot of CloudFormation code. I created a Macro once to help out with exactly that but still. So let's go ahead and add that then.


.....

core.Tag("Cost", "Testning").add(vpc)

app.synth()

Wow! That's it! ONE extra line of code and I get the tag on all resources that support tags.

Now let us synthesize the template and deploy the app. Then we just run the command.

cdk synth
cdk deploy

All done! The stack has been deployed to CloudFormation and the VPC is created. This is so nice. It also possible to deploy different stacks to different regions by adding extra parameters, but that I'll show in a different post!

If there is one thing I would recommend it is to also version control the generated template in your source code repository. The reason being that then you can inspect that changes you made change what you expect it to change in the CloudFormation template.

Happy hacking and enjoy the CDK, I know I will!!