logo
Menu
CDK Cloud Development Kit

CDK Cloud Development Kit

Unleashing the Power of Cloud Development: Exploring the CDK.

Published May 2, 2024

AWS Knowledge Series

Welcome to the second installment of my Knowledge Series, where I aim to compile a wealth of high-quality content on various AWS topics, making it freely available to all. In this post, we'll embark on a deep dive into the AWS Cloud Development Kit (CDK), exploring advanced topics such as multi-environment deployments, and custom constructs, and providing an interactive guide to help you kickstart your CDK journey using the comprehensive AWS CDK documentation.
By the end of this deep dive into the AWS CDK, you'll have gained a comprehensive understanding of its advanced capabilities, empowering you to harness the full potential of infrastructure as code in your AWS projects. Whether you're a seasoned cloud architect or a newcomer to the world of AWS, the CDK offers a powerful set of tools and techniques to streamline your infrastructure provisioning workflows and accelerate your journey to the cloud. So, let's dive in and unlock the true power of the AWS CDK together!

Challenges of Cloud Infrastructure

Different teams may have different deployment workflows for infrastructure and code, leading to delays and risks when accessing required services. Manual configuration of environments can result in inconsistencies between testing and development environments. Over time, deployed environments may drift, potentially causing disruptions during production. Standing up in new environments is time-consuming and error-prone. Many of these challenges can be mitigated through the adoption of Infrastructure as Code (IaC).

IaC

Managing your infrastructure should be as easy as managing your application code.
Similar to version control systems (VCS) and automated testing used for application code, IaC offers numerous advantages. It involves defining infrastructure and its configuration in human-readable files.

Approaches for IaC

Procedural Approach

With the procedural code, we are defining the process of creating our infrastructure. When using the procedural approach we will run into some challenges. It doesn't consider the current state of the infrastructure, if we deploy an ec2 instance and we want to resize it, this approach doesn't know how to do it.

Declarative Approach

With the declarative approach, we are defining the state of our infrastructure. If we now launch resources with this script, we can go into the service that manages this script and it knows which exact resource instance has to be changed. Here the challenge is that we need a service to map the state to the actual infrastructure. Another challenge is that it will be more difficult to create reusable components.
We get the best benefit of both of these approaches when we pair them and that's what the CDK does.
There are multiple different solutions to achieve this goal (IaC). There are some third party and some AWS services which help us build infrastructure.
  • SAM (Serverless Application Model)
  • Terraform
  • CloudFormation
  • Pulumi

CDK

The CDK is a framework to provision cloud resources using a programming language.

Benefits CDK

CDK lets us use familiar programming languages, avoiding the need to learn new CloudFormation syntax. It helps unify development for both code and infrastructure while maintaining AWS support.

CDK Structure

When using the CDK to provision cloud resources in our account, we create Resources, each with its identifier. These Resources represent the infrastructure elements built using the CDK, and their identifiers enable future referencing.
To facilitate reuse across our organization, we utilize Constructs, which are logical groupings of Resources. If we need to add additional Resources that are related to the Construct but should remain separate, we can include them alongside individual Resources within Constructs. This higher-level organization is called a Stack, which is the deployment unit within the CDK. Stacks correspond to CloudFormation Stacks and share their limitations.
Every Stack is associated with an environment specifying the account and region, either explicitly or implicitly defined. At the top level of a CDK project is the CDK App, serving as the root of the context tree and capable of containing one or more Stacks.
AWS CDK Structure

Constructs

Constructs serve as the fundamental components of AWS CDK applications, encapsulating one or more CloudFormation resources along with their configurations. With constructs, we can incrementally build our applications, importing and configuring them piece by piece.
These constructs are essentially classes that we import into our CDK apps. While the AWS Construct Library provides a rich set of pre-built constructs, we also have the flexibility to craft and share our own or leverage constructs developed by third parties.
The primary motivation behind constructing these components is the ability to reuse them in future projects, streamlining development efforts and promoting consistency across applications.

Initialization

When initializing constructs, they all require three parameters:
  1. Scope: This defines the construct's parent or owner, which can be either a stack or another construct. The scope determines where the construct fits in the construct tree.
  2. ID: An identifier that must be unique within the scope. This ID is crucial as it's used to generate unique identifiers like resource names and AWS CloudFormation logical IDs.
  3. Props: A set of properties defining the construct's initial configuration. Higher-level constructs often offer more default props, simplifying configuration.
1
2
3
4
5
const instance = new ec2.Instance(this, 'targetInstance', {
vpc: vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO),
machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }),
});
In this example from the AWS docs, "this" is frequently employed as the scope, denoting that the resource should be provisioned in the parent container. Following this, each resource is assigned a unique ID within the stack. Furthermore, we specify the parameters necessary for customizing the resource.

Construct Library

The AWS Construct Library contains a collection of constructs that are developed and maintained by AWS. However, we can also build our construct library using npm.
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Instance.html
Custom Construct Library
To build, use, and distribute custom components, we can utilize an npm registry. Sharing our code with others is facilitated through an npm registry.
To create custom components for sharing, we initiate a project with the CDK, aiming to minimize the number of files using the command:
1
cdk init --language=typescript lib
Once we define our components in this file, we need to compile the project to generate target files, as specified in the `package.json`.
Before publishing, we typically scope the project (refer to documentation). After scoping, we log in to npm to publish the package.
Finally, we can import the custom construct library into other projects as needed.

Composition

Composition is the key pattern for defining higher-level abstraction through constructs. A high-level construct can be composed of any number of lower-level constructs. With composition, we define reusable components and share them like any other code.

Construct Tree

Constructs are nested within other constructs using the `scope` argument, which is passed to every construct starting from the root, the App class. This hierarchical arrangement of constructs is known as the construct tree in CDK.

Stacks Patterns

These constructs mirror CloudFormation (CF) stacks, employing similar design patterns to circumvent limitations and maintain project organization. Common CF design patterns include Nested, Distributed, Main, and Skeleton. These patterns aim to sidestep limitations and adhere to consistent design principles.

Structure of a CDK Project

Once the project is created, we'll notice that the CDK has generated several files for us. The `cdk.json` file references the `bin/typescript-cdk.ts` file, serving as the project's entry point.
CDK Json
The `package.json` file reveals the dependencies installed in our project. As we begin referencing additional AWS services, we'll need to add more dependencies.
CDK Package JSON
By default, the CDK includes tests in the project, allowing us to test the infrastructure we've developed.

CDK Test
Types of CDK Constructs

L1

These are constructus which are a direct map to which are available in CloudFormation. In the CDK Documentation, these are going to be referred to as the CFN resources.

L2

These constructs are specifically written for the SDK. Which is going to be more easy to deploy. In the CDK these are going to be referred to as the CDK Constructs. We have to make sure that the Constructs that we are using are Stable, when the CDK gets updated we may have to rewrite our entire code.

L3

Level 3 Constructs are often found in organizations or development teams with established guidelines. These Constructs can represent entire architectures ready for deployment. While there's no strict limit on nesting Constructs, three common categories exist along with their levels of abstraction. As Constructs ascend in level, they become more opinionated in their design.

CDK Workflow

Init
To create a project, we use the `init` command followed by the desired programming language.
1
cdk init app --language javascript
There are different templates from which we can choose: "app", "lib" and. Then there also is the programming language from which we can choose from.
Bootstrap
The Bootstrap step is not required every time; it's a one-time operation per environment. CDK initiates the creation of its resources to facilitate stack management. An environment is defined by a combination of the account number and the region.
1
cdk bootstrap aws://123456789012/us-east-1
Synth
Once infrastructure programming is complete, we can initiate the synthesis of the project. This step involves taking our code and generating a CloudFormation template. While this command is executed automatically during deployment, we can also run it individually as needed.
(optionally)
1
cdk synth
Deploy
During the deployment phase, AWS will take our CloudFormation Stacks and provision them. Here, we deploy Stacks, which can be listed individually. If there are multiple stacks, we should specify the ones we want to launch.
1
cdk deploy
Update
One advantage of declarative approaches is the ability to modify infrastructure even after provisioning in the AWS Cloud. During the Update step, we can make changes to our CDK project. To update a project we can just redeploy it.
1
cdk deploy

Stack Patterns

Functional Stack
To begin, within the `lib` directory, we can create a subdirectory named "stacks." Within this directory, we'll create a separate directory for each function of the app. Instead of initializing the `MasterFullStack` in the main file, we'll initialize all the stack files.

Interstack Communication

Just like having communication between different constructs, we want to gain communication between different stacks, this is called Interstack communication. There are multiple ways on how to implement this functionality:
Passing Properties as Paraterms
1
2
3
const app = new cdk.App()
const websiteStack = websiteStackCdk(app, "websiteStack", props);
new backendStack = backendStack(app, "backendStack" , props: websiteStack.someValue);
Passing the entire Stack
1
2
3
const app = new cdk.App()
const websiteStack = websiteStackCdk(app, "websiteStack", props);
new backendStack = backendStack(app, "anotherStack", props: websiteStack);

Multi Environment Concepts

In the realm of cloud computing, the term "environment" holds multifaceted significance. It encompasses not only the AWS Environment, where distinct environments like testing, production, and development reside but also extends to the broader business or "code" environment—a space where code deployment occurs, often resembling a sandbox for experimentation.

Characteristics of Environments

Each environment carries specific characteristics that demand careful consideration. For instance, in the developmental realm, cost-efficient solutions are favored, prompting the avoidance of large, costly instances. Conversely, the production environment mandates stringent isolation and security measures to safeguard critical operations.
Given the diverse requirements across environments, the challenge lies in harmonizing workloads to suit these distinct characteristics. The goal? To avoid redundancy while ensuring seamless deployment across varied environments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const env = {
environment: "dev"
}

const dev = {
env: {account: "123456789", region: "us-west-2"},
ec2Default: "M4.xLarge"
};

const test = {
env: {account: "11245678", region: "us-west-1"},
ec2Default: "M3.nano"
};

switch (env.environment) {
case "dev": {
//deploy this stack or the same stack with different parameters
}

case "test": {
//deploy this stack or the same stack with different parameters as the env
const stackWebsite = new stackWebsiteCdn(app, "CdnStack", env)
}
}

Props

In the CDK we can have props passed into our custom construct. For this, we can choose the lib template when we create the project. The lib template will include an export Interface. As we can see this export interface is meant for the props passed into the construct.
1
cdk init lib --language javascript
1
2
3
export interface CustomComponent {
// Define construct properties here
}
These components (constructs) are going to be L2 or L3 constructs and are in most cases going to be uploaded to a repository like npm.
In the CDK we also can pass props into the stacks. We can do this using an export interface as well, however, we can see that this time we are extending a class from StackProps.
1
2
3
export interface StackPattern extends from.StackProps {
// Define properties here
}

Build your Infastrcuture

In this interactive guide, I'll walk you through the process of creating an AWS CDK project step by step. Additionally, I'll provide you with valuable resources to further enhance and expand your CDK skills.
If you need any help throughout the guide you can always reference the aws docs or ask a question on repost.
AWS Docs
Repost

How can you start now?

To be able to start creating AWS we first need to have the AWS CLI and the cdk installed. To install the AWS CDK run:
1
npm install -g aws-cdk
To check if the AWS CDK has been downloaded successfully you can run:
1
cdk --version
If you now get a version number back it means that you have successfully installed the CDK.
You now have to select a programming language in which you want to write your infrastructure, in this guide I will choose Javascript. Run the following commands to create a dir, go into that dir, and then create a CDK project in the programming language JavaScript.
1
2
3
mkdir my-project
cd my-project
cdk init app --language javascript
(Optional)
If you want to install any third-party or event constructs that you have made you can import these into the CDK project
1
npm install @aws-cdk/aws-codestar-alpha
This example was taken from the AWS docs, however, you can just replace "@aws-cdk/aws-codestar-alpha" with your package name. To use that construct in your file you have to import it.
1
const { s3 } = require('aws-cdk-lib/aws-s3');
To check which packages you have installed you can go to package.json file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"name": "my-package",
"version": "0.1.0",
"bin": {
"my-package": "bin/my-package.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "jest",
"cdk": "cdk"
},
"devDependencies": {
"@types/jest": "^26.0.10",
"@types/node": "10.17.27",
"jest": "^26.4.2",
"ts-jest": "^26.2.0",
"aws-cdk": "2.16.0",
"ts-node": "^9.0.0",
"typescript": "~3.9.7"
},
"dependencies": {
"aws-cdk-lib": "2.16.0",
"constructs": "^10.0.0",
"source-map-support": "^0.5.16"
}
}
Now we will create a S3 Bucket and a ec2 instance, to make this a bit easier we are going to use L2 Constructs.

Learn the Docs

If you now create further projects in the realm of the AWS CDK you are always going to use the CDK docs. You need to get familiar with them.
1
2
3
4
5
6
new s3.Bucket(scope, 'Bucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
enforceSSL: true,
versioned: true,
});
AWS CDK Docs Example
AWS CDK Docs Init
AWS CDK Docs Properties
The CDK Properties must be or can be defined in the Construct, if the property has a question mark it means that it is optional, if not it is mandatory and the code will most likely fail if not enfored.

Demo project

There are many great websites from where you can get inspiration for your CDK Project, this is one of my personal favorites.

Thanks to

I wanted to take a moment to express my sincere gratitude to all those who have contributed to my learning journey with the AWS CDK. Without the invaluable resources, documentation, and tutorial videos provided by individuals and organizations in the AWS community, I would not have been able to write this article.

My personal experience

When I embarked on my journey to learn about the AWS CDK, I found it incredibly fascinating. Here was a tool that allowed me to leverage my programming skills to create and manage AWS resources—an opportunity that seemed both exciting and daunting at first. Like many beginners, I struggled to find the right starting point. The sheer volume of information and the complexity of the subject matter made it feel like an uphill battle.
However, as I dedicated countless hours to working with the CDK, reading documentation, and watching tutorials, I began to unlock its potential. With each tutorial completed and each concept understood, I gained confidence in my abilities and started to see tangible results in my projects.
What fascinated me most about the CDK was its ability to bridge the gap between traditional infrastructure management and modern software development practices. Suddenly, infrastructure became code, and I could apply familiar programming patterns and techniques to automate the creation and management of cloud resources.
But it wasn't all smooth sailing. There were moments of frustration and exhaustion—times when I felt overwhelmed by the complexity of the CDK and the seemingly endless list of AWS services and features to learn. Yet, with perseverance and determination, I pushed through the challenges and continued to build my knowledge and expertise.
Now, as I reflect on my journey, I realize how far I've come. This blog post is a culmination of my experiences—a testament to the hours spent mastering the CDK and the valuable lessons learned along the way. It serves as a guide for others who may be embarking on their own CDK journey, offering insights, tips, and resources to help them navigate the learning curve more efficiently.
So, if you're just starting out with the CDK, know that the journey may be challenging, but the rewards are well worth it. With dedication and persistence, you too can harness the power of the AWS CDK to build scalable, efficient, and reliable cloud infrastructure.
 

1 Comment