Skip to content

Cdk

Chapter 34: AWS CDK - Cloud Development Kit

Section titled “Chapter 34: AWS CDK - Cloud Development Kit”

Infrastructure as Code with Programming Languages

Section titled “Infrastructure as Code with Programming Languages”

AWS Cloud Development Kit (CDK) is an open-source software development framework to define cloud infrastructure in code and provision it through AWS CloudFormation.

AWS CDK Overview
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | AWS CDK | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Code in | | CDK | | CloudFor-| |
| | Language | | Synthesize| | mation | |
| | | | | | Template | |
| | - Type | | - CFN | | | |
| | Script | | Template| | - Deploy | |
| | - Python | | - YAML/ | | - Manage | |
| | - Java | | JSON | | | |
| +----------+ +----------+ +----------+ |
| |
+------------------------------------------------------------------+
LanguageFile ExtensionNotes
TypeScript.tsPrimary language, best support
JavaScript.jsNode.js runtime
Python.pyPopular for DevOps
Java.javaEnterprise applications
C#.cs.NET developers
Go.goGrowing support

CDK Architecture
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | CDK App | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Stack 1 | | Stack 2 | | Stack N | |
| | | | | | | |
| | - VPC | | - ECS | | - Lambda | |
| | - Subnets| | - ALB | | - API GW | |
| +----------+ +----------+ +----------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Constructs| | Constructs| | Constructs| |
| | | | | | | |
| | - L1 | | - L2 | | - L3 | |
| | - L2 | | - L3 | | | |
| +----------+ +----------+ +----------+ |
| |
+------------------------------------------------------------------+
CDK Construct Levels
+------------------------------------------------------------------+
| |
| L1 Constructs (Cfn Resources) |
| +------------------------------------------------------------+ |
| | | |
| | - Direct mapping to CloudFormation resources | |
| | - Names start with "Cfn" (e.g., CfnBucket, CfnVPC) | |
| | - Requires all properties to be set | |
| | - No defaults or validation | |
| | | |
| | Example: | |
| | new CfnBucket(this, 'MyBucket', { | |
| | bucketName: 'my-bucket', | |
| | versioningConfiguration: { | |
| | status: 'Enabled' | |
| | } | |
| | }); | |
| | | |
| +------------------------------------------------------------+ |
| |
| L2 Constructs (Higher-Level) |
| +------------------------------------------------------------+ |
| | | |
| | - AWS best practices built-in | |
| | - Sensible defaults | |
| | - Helper methods and properties | |
| | - Most commonly used | |
| | | |
| | Example: | |
| | new Bucket(this, 'MyBucket', { | |
| | versioned: true, | |
| | encryption: BucketEncryption.S3_MANAGED, | |
| | blockPublicAccess: BlockPublicAccess.BLOCK_ALL | |
| | }); | |
| | | |
| +------------------------------------------------------------+ |
| |
| L3 Constructs (Patterns) |
| +------------------------------------------------------------+ |
| | | |
| | - Complete solutions for common use cases | |
| | - Multiple resources bundled together | |
| | - Opinionated configurations | |
| | | |
| | Examples: | |
| | - aws-cdk-lib/aws-apigateway.LambdaRestApi | |
| | - aws-cdk-lib/aws-ecs-patterns.ApplicationLoadBalancedFargateService |
| | - aws-cdk-lib/aws-s3-deployment.BucketDeployment | |
| | | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

CDK Project Structure
+------------------------------------------------------------------+
| |
| my-cdk-app/ |
| +------------------------------------------------------------+ |
| | | |
| | cdk.json # CDK configuration | |
| | package.json # Node.js dependencies | |
| | tsconfig.json # TypeScript configuration | |
| | cdk.context.json # Context values (cached) | |
| | | |
| | bin/ | |
| | my-cdk-app.ts # Entry point | |
| | | |
| | lib/ | |
| | my-cdk-app-stack.ts # Stack definition | |
| | my-cdk-app-stack.ts # Additional stacks | |
| | | |
| | test/ | |
| | my-cdk-app.test.ts # Unit tests | |
| | | |
| | node_modules/ # Dependencies | |
| | | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class MyCdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Create VPC
const vpc = new ec2.Vpc(this, 'MyVpc', {
maxAzs: 2,
natGateways: 1,
});
// Create S3 Bucket
const bucket = new s3.Bucket(this, 'MyBucket', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// Create Lambda Function
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = async function(event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: "Hello from CDK!"
};
};
`),
});
// Grant Lambda permission to read from bucket
bucket.grantRead(fn);
}
}
from aws_cdk import (
Stack,
aws_ec2 as ec2,
aws_s3 as s3,
aws_lambda as lambda_,
RemovalPolicy,
)
from constructs import Construct
class MyCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Create VPC
vpc = ec2.Vpc(
self, "MyVpc",
max_azs=2,
nat_gateways=1,
)
# Create S3 Bucket
bucket = s3.Bucket(
self, "MyBucket",
versioned=True,
encryption=s3.BucketEncryption.S3_MANAGED,
block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
removal_policy=RemovalPolicy.DESTROY,
)
# Create Lambda Function
fn = lambda_.Function(
self, "MyFunction",
runtime=lambda_.Runtime.NODEJS_18_X,
handler="index.handler",
code=lambda_.Code.from_inline("""
exports.handler = async function(event) {
return {
statusCode: 200,
body: "Hello from CDK!"
};
};
"""),
)
# Grant Lambda permission to read from bucket
bucket.grant_read(fn)

Terminal window
# Initialize new CDK app
cdk init app --language typescript
cdk init app --language python
cdk init app --language java
# Bootstrap CDK (first time setup)
cdk bootstrap aws://123456789012/us-east-1
# Synthesize CloudFormation template
cdk synth
# Synthesize specific stack
cdk synth MyStack
# Diff changes
cdk diff
# Deploy stack
cdk deploy
# Deploy specific stack
cdk deploy MyStack
# Deploy with parameters
cdk deploy --parameters Env=prod
# Deploy with context
cdk deploy --context key=value
# List stacks
cdk list
cdk ls
# Destroy stack
cdk destroy
# Destroy specific stack
cdk destroy MyStack
# Watch for changes (hotswap)
cdk deploy --hotswap
# Import existing resource
cdk import
# Generate CloudFormation template
cdk synth > template.yaml
# Context management
cdk context --list
cdk context --clear
# Doctor (troubleshooting)
cdk doctor

// Create VPC with custom configuration
const vpc = new ec2.Vpc(this, 'MyVpc', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 3,
natGateways: 1,
subnetConfiguration: [
{
cidrMask: 24,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
{
cidrMask: 28,
name: 'Database',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
],
gatewayEndpoints: {
S3: ec2.GatewayVpcEndpointAwsService.S3,
},
});
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
// Create ECS cluster
const cluster = new ecs.Cluster(this, 'MyCluster', {
vpc: vpc,
});
// Create Fargate service with load balancer
const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(
this,
'MyFargateService',
{
cluster: cluster,
cpu: 256,
desiredCount: 2,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('nginx:latest'),
containerPort: 80,
},
memoryLimitMiB: 512,
publicLoadBalancer: true,
}
);
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as lambda from 'aws-cdk-lib/aws-lambda';
// Create Lambda function
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
});
// Create API Gateway
const api = new apigateway.LambdaRestApi(this, 'MyApi', {
handler: fn,
restApiName: 'My Service API',
defaultCorsPreflightOptions: {
allowOrigins: apigateway.Cors.ALL_ORIGINS,
allowMethods: apigateway.Cors.ALL_METHODS,
},
});

CDK Pipelines Architecture
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | CDK Pipeline | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Source | | Build | | Deploy | |
| | Stage | | Stage | | Stage | |
| | | | | | | |
| | - Code | | - Synth | | - Dev | |
| | Commit | | - Test | | - Stage | |
| | | | | | - Prod | |
| +----------+ +----------+ +----------+ |
| |
+------------------------------------------------------------------+
import * as codecommit from 'aws-cdk-lib/aws-codecommit';
import * as pipelines from 'aws-cdk-lib/pipelines';
// Create repository
const repo = new codecommit.Repository(this, 'MyRepo', {
repositoryName: 'my-repo',
});
// Create pipeline
const pipeline = new pipelines.CodePipeline(this, 'MyPipeline', {
synth: new pipelines.ShellStep('Synth', {
input: pipelines.CodePipelineSource.codeCommit(repo, 'main'),
commands: [
'npm ci',
'npm run build',
'npx cdk synth',
],
}),
});
// Add stages
const devStage = pipeline.addStage(new MyStack(this, 'Dev', {
env: { account: '123456789012', region: 'us-east-1' },
}));
const prodStage = pipeline.addStage(new MyStack(this, 'Prod', {
env: { account: '123456789013', region: 'us-east-1' },
}));
// Add manual approval before prod
prodStage.addPre(new pipelines.ManualApprovalStep('ApproveDeployment'));

CDK Best Practices
+------------------------------------------------------------------+
| |
| 1. Use L2 constructs over L1 when possible |
| +------------------------------------------------------------+ |
| | - L2 constructs have best practices built-in | |
| | - Less code to write | |
| +------------------------------------------------------------+ |
| |
| 2. Create reusable constructs |
| +------------------------------------------------------------+ |
| | - Extend Construct class | |
| | - Encapsulate common patterns | |
| +------------------------------------------------------------+ |
| |
| 3. Use context for environment-specific values |
| +------------------------------------------------------------+ |
| | - Use cdk.json for configuration | |
| | - Use --context flag for overrides | |
| +------------------------------------------------------------+ |
| |
| 4. Write tests for stacks |
| +------------------------------------------------------------+ |
| | - Use Jest for TypeScript | |
| | - Test resource creation and properties | |
| +------------------------------------------------------------+ |
| |
| 5. Use CDK Pipelines for CI/CD |
| +------------------------------------------------------------+ |
| | - Automate deployments | |
| | - Use stages for environments | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Exam Tip

Key Exam Points
+------------------------------------------------------------------+
| |
| 1. CDK generates CloudFormation templates |
| |
| 2. L1 constructs = CFN resources (Cfn prefix) |
| |
| 3. L2 constructs = Higher-level with best practices |
| |
| 4. L3 constructs = Complete patterns/solutions |
| |
| 5. CDK supports TypeScript, Python, Java, C#, Go |
| |
| 6. Use cdk synth to generate CloudFormation template |
| |
| 7. Use cdk diff to see changes before deployment |
| |
| 8. CDK Pipelines for CI/CD of infrastructure |
| |
| 9. Bootstrap is required for first-time CDK use |
| |
| 10. Constructs are the building blocks of CDK apps |
| |
+------------------------------------------------------------------+

Chapter 34 Summary
+------------------------------------------------------------------+
| |
| AWS CDK Core Concepts |
| +------------------------------------------------------------+ |
| | - Infrastructure as Code using programming languages | |
| | - Synthesizes to CloudFormation templates | |
| | - Supports multiple languages | |
| +------------------------------------------------------------+ |
| |
| Construct Levels |
| +------------------------------------------------------------+ |
| | - L1: Direct CFN mapping (CfnXxx) | |
| | - L2: Higher-level with defaults | |
| | - L3: Complete patterns | |
| +------------------------------------------------------------+ |
| |
| Key Commands |
| +------------------------------------------------------------+ |
| | - cdk init: Create new project | |
| | - cdk synth: Generate template | |
| | - cdk deploy: Deploy stack | |
| | - cdk diff: Show changes | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Previous Chapter: Chapter 33: AWS CloudFormation - Infrastructure as Code Next Chapter: Chapter 35: AWS Systems Manager