Next level Infrastructure deployment with CDK

Pascal Euhus
4 min readSep 4, 2020

Few years ago few people cared about coded infrastructure, there was configmanagement and application code, however the server specifications, networks and other basic infrastructure were still admin concerns. Then Infrastructure as Code began to rise and multiple tools entered the market. AWS Cloudformation, Hashicorp Terraform, GCP Deployment Manager, Azure Resource Manager to mention few of them, on top of them several frameworks adopted those tools under the hood like eg. serverless framework.

Having a closer look, the common thing is, most of them use (kind of) YAML/ JSON syntax to describe the resources. Depending on your needs you can choose between cloud provider independent frameworks eg Terraform or the official supported tools from the provider of your choice. All in all IaC requires you to have another language alongside with your application code.

Since AWS released the Cloud Development Kit things changed. One could use eg Typescript for both application and infrastructure. Another abstraction level which makes you as a Cloudformation or Terraform newbie feeling more comfortable to use them. In addition you have the power of real programming constructs. CDK evolves fast and it could be the next way of coding infrastructure and has support for different IaC tools.

The CDK using Terraform is still in alpha, however for Cloudformation it is in a state to give a try. The abstraction makes IaC more readable and programmers feel more like writing code for their application. They dont have to take that much effort in thinking about the corresponding permissions and resource definitions for their infrastructure. CDK will take care of that automatically and decreases the learning curve for IaC.

At the time of writing this article CDK for Terraform currently supports Python and Typescript, whereas CDK for Cloudformation has support for Python, Typescript, Javascript, Java and C#/.Net.

The concept is pretty easy. A CDK-App consists of Stacks, logically grouped systems deployed as one unit. A Stack in turn has multiple constructs, technically grouped units eg. you can group application and storage (database, s3…) into two seperate stacks, which then can be deployed independently.

The following code is from the CDK (Cloudformation) sample templates, you can simply start using:

mkdir example-cdk && cd example-cdk && npx cdk init sample --language typescript

import * as sns from '@aws-cdk/aws-sns';
import * as subs from '@aws-cdk/aws-sns-subscriptions';
import * as sqs from '@aws-cdk/aws-sqs';
import * as cdk from '@aws-cdk/core';

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

const queue = new sqs.Queue(this, 'ExampleCdkQueue', {
visibilityTimeout: cdk.Duration.seconds(300)
});

const topic = new sns.Topic(this, 'ExampleCdkTopic');

topic.addSubscription(new subs.SqsSubscription(queue));
}
}

The above example will result in the following resources to be created:

{
"Resources": {
"ExampleCdkQueue9C84316C": {
"Type": "AWS::SQS::Queue",
"Properties": {
"VisibilityTimeout": 300
},
"Metadata": {
"aws:cdk:path": "ExampleCdkStack/ExampleCdkQueue/Resource"
}
},
"ExampleCdkQueuePolicyE9BDE14D": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sqs:SendMessage",
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "ExampleCdkTopic95889CD0"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Resource": {
"Fn::GetAtt": [
"ExampleCdkQueue9C84316C",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"Queues": [
{
"Ref": "ExampleCdkQueue9C84316C"
}
]
},
"Metadata": {
"aws:cdk:path": "ExampleCdkStack/ExampleCdkQueue/Policy/Resource"
}
},
"ExampleCdkQueueExampleCdkStackExampleCdkTopicE7E4E8F61E90FB4F": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Protocol": "sqs",
"TopicArn": {
"Ref": "ExampleCdkTopic95889CD0"
},
"Endpoint": {
"Fn::GetAtt": [
"ExampleCdkQueue9C84316C",
"Arn"
]
}
},
"Metadata": {
"aws:cdk:path": "ExampleCdkStack/ExampleCdkQueue/ExampleCdkStackExampleCdkTopicE7E4E8F6/Resource"
}
},
"ExampleCdkTopic95889CD0": {
"Type": "AWS::SNS::Topic",
"Metadata": {
"aws:cdk:path": "ExampleCdkStack/ExampleCdkTopic/Resource"
}
}
}
}

Another big advantage is the capability of writing unit test for your Infrastructure. This is the corresponding unit test for the ExampleStack:

import { expect as expectCDK, haveResource } from '@aws-cdk/assert';
import * as cdk from '@aws-cdk/core';
import * as ExampleCdk from '../lib/example-cdk-stack';

test('SQS Queue Created', () => {
const app = new cdk.App();
// WHEN
const stack = new ExampleCdk.ExampleCdkStack(app, 'MyTestStack');
// THEN
expectCDK
(stack).to(haveResource("AWS::SQS::Queue",{
VisibilityTimeout: 300
}));
});

test('SNS Topic Created', () => {
const app = new cdk.App();
// WHEN
const stack = new ExampleCdk.ExampleCdkStack(app, 'MyTestStack');
// THEN
expectCDK
(stack).to(haveResource("AWS::SNS::Topic"));
});

TL;DR;

CDK brings IaC to a new level. With the ability not to be stuck together with Cloudformation and therefore AWS and the growing support for various programming languages it really strikes the hurdles to write IaC. The approach of CDK makes a stack even more homogenous and testable for CI/CD purposes. With Terraform support it will even become cloud provider independent.

Finally, there is an official AWS workshop here to get started with ease.

--

--

Pascal Euhus

Software-Engineer and DevOps-Enthusiast, AWS Solutions Architect Professional, GCP Professional Cloud Architect