AWS CDK (Cloud Development Kit)
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”34.1 Overview
Section titled “34.1 Overview”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 | | | || +----------+ +----------+ +----------+ || |+------------------------------------------------------------------+Supported Languages
Section titled “Supported Languages”| Language | File Extension | Notes |
|---|---|---|
| TypeScript | .ts | Primary language, best support |
| JavaScript | .js | Node.js runtime |
| Python | .py | Popular for DevOps |
| Java | .java | Enterprise applications |
| C# | .cs | .NET developers |
| Go | .go | Growing support |
34.2 CDK Architecture
Section titled “34.2 CDK Architecture”CDK Structure
Section titled “CDK Structure” 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 | | | || +----------+ +----------+ +----------+ || |+------------------------------------------------------------------+Construct Levels
Section titled “Construct Levels” 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 | || | | || +------------------------------------------------------------+ || |+------------------------------------------------------------------+34.3 CDK Project Structure
Section titled “34.3 CDK Project Structure”Project Layout
Section titled “Project Layout” 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 | || | | || +------------------------------------------------------------+ || |+------------------------------------------------------------------+Basic Stack Example (TypeScript)
Section titled “Basic Stack Example (TypeScript)”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); }}Python Stack Example
Section titled “Python Stack Example”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)34.4 CDK CLI Commands
Section titled “34.4 CDK CLI Commands”# Initialize new CDK appcdk init app --language typescriptcdk init app --language pythoncdk init app --language java
# Bootstrap CDK (first time setup)cdk bootstrap aws://123456789012/us-east-1
# Synthesize CloudFormation templatecdk synth
# Synthesize specific stackcdk synth MyStack
# Diff changescdk diff
# Deploy stackcdk deploy
# Deploy specific stackcdk deploy MyStack
# Deploy with parameterscdk deploy --parameters Env=prod
# Deploy with contextcdk deploy --context key=value
# List stackscdk listcdk ls
# Destroy stackcdk destroy
# Destroy specific stackcdk destroy MyStack
# Watch for changes (hotswap)cdk deploy --hotswap
# Import existing resourcecdk import
# Generate CloudFormation templatecdk synth > template.yaml
# Context managementcdk context --listcdk context --clear
# Doctor (troubleshooting)cdk doctor34.5 CDK Constructs Deep Dive
Section titled “34.5 CDK Constructs Deep Dive”VPC Construct
Section titled “VPC Construct”// Create VPC with custom configurationconst 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, },});ECS Fargate Service
Section titled “ECS Fargate Service”import * as ecs from 'aws-cdk-lib/aws-ecs';import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
// Create ECS clusterconst cluster = new ecs.Cluster(this, 'MyCluster', { vpc: vpc,});
// Create Fargate service with load balancerconst 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, });API Gateway with Lambda
Section titled “API Gateway with Lambda”import * as apigateway from 'aws-cdk-lib/aws-apigateway';import * as lambda from 'aws-cdk-lib/aws-lambda';
// Create Lambda functionconst fn = new lambda.Function(this, 'MyFunction', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromAsset('lambda'),});
// Create API Gatewayconst api = new apigateway.LambdaRestApi(this, 'MyApi', { handler: fn, restApiName: 'My Service API', defaultCorsPreflightOptions: { allowOrigins: apigateway.Cors.ALL_ORIGINS, allowMethods: apigateway.Cors.ALL_METHODS, },});34.6 CDK Pipelines
Section titled “34.6 CDK Pipelines”CDK Pipelines Overview
Section titled “CDK Pipelines Overview” CDK Pipelines Architecture+------------------------------------------------------------------+| || +------------------------+ || | CDK Pipeline | || +------------------------+ || | || +---------------------+---------------------+ || | | | || v v v || +----------+ +----------+ +----------+ || | Source | | Build | | Deploy | || | Stage | | Stage | | Stage | || | | | | | | || | - Code | | - Synth | | - Dev | || | Commit | | - Test | | - Stage | || | | | | | - Prod | || +----------+ +----------+ +----------+ || |+------------------------------------------------------------------+Pipeline Example
Section titled “Pipeline Example”import * as codecommit from 'aws-cdk-lib/aws-codecommit';import * as pipelines from 'aws-cdk-lib/pipelines';
// Create repositoryconst repo = new codecommit.Repository(this, 'MyRepo', { repositoryName: 'my-repo',});
// Create pipelineconst 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 stagesconst 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 prodprodStage.addPre(new pipelines.ManualApprovalStep('ApproveDeployment'));34.7 Best Practices
Section titled “34.7 Best Practices”CDK Best Practices
Section titled “CDK Best Practices” 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 | || +------------------------------------------------------------+ || |+------------------------------------------------------------------+34.8 Why This Matters in DevOps/SRE
Section titled “34.8 Why This Matters in DevOps/SRE”CDK is a powerful abstraction over CloudFormation, enabling developers to define infrastructure using familiar programming languages. SREs benefit from type safety, testing, and reusability.
CDK in DevOps/SRE+------------------------------------------------------------------+| || SRE Infrastructure Principles: || || 1. Infrastructure as Code with Programming Languages || +----------------------------------------------------------+ || | - Use TypeScript/Python/Java for infrastructure | || | - Leverage IDE features: autocomplete, refactoring | || | - Write unit tests for infrastructure logic | || +----------------------------------------------------------+ || || 2. Composability & Reusability || +----------------------------------------------------------+ || | - Create custom constructs for organization patterns | || | - Publish constructs to internal registries | || | - Share tested patterns across teams | || +----------------------------------------------------------+ || || 3. Safe Deployments || +----------------------------------------------------------+ || | - cdk diff shows exact CloudFormation changes | || | - cdk synth generates template for review | || | - CDK Pipelines provide self-mutating CI/CD | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+34.9 Linux Systems Perspective
Section titled “34.9 Linux Systems Perspective”CDK Automation from Arch Linux
Section titled “CDK Automation from Arch Linux”# Install Node.js and CDK on Arch Linuxsudo pacman -S nodejs npm python-pipgnpm install -g aws-cdk
# CDK project setupcdk init app --language typescript
# Common CDK commandscdk list # List stackscdk synth my-stack # Generate CloudFormationcdk diff my-stack # Show changescdk deploy my-stack # Deploy stackcdk destroy my-stack # Delete stack
# CDK bootstrap (one-time per account/region)cdk bootstrap aws://123456789012/us-east-1
# CDK Pipeline setupcdk init --pipeline-type classic-app --language typescript34.10 Common Mistakes & Anti-Patterns
Section titled “34.10 Common Mistakes & Anti-Patterns” CDK Anti-Patterns+------------------------------------------------------------------+| || ❌ Mistake 1: Using L1 Constructs for Everything || +----------------------------------------------------------+ || | Problem: Writing verbose Cfn* resources directly | || | Impact: More code, less best practices | || | Fix: Use L2/L3 constructs when available | || +----------------------------------------------------------+ || || ❌ Mistake 2: Not Running cdk synth Before Deploy || +----------------------------------------------------------+ || | Problem: Deploying without seeing generated CloudFormation| || | Impact: Unexpected resource changes in production | || | Fix: Always run cdk diff/synth before deploy | || +----------------------------------------------------------+ || || ❌ Mistake 3: Hardcoding Credentials in Code || +----------------------------------------------------------+ || | Problem: Secrets in source code | || | Impact: Security vulnerabilities, credential exposure | || | Fix: Use Secrets Manager or Parameter Store | || +----------------------------------------------------------+ || || ❌ Mistake 4: Not Testing CDK Stacks || +----------------------------------------------------------+ || | Problem: No unit tests for infrastructure code | || | Impact: Bugs reach production, unexpected failures | || | Fix: Write Jest/Pytest unit tests for stacks | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+34.11 Interview Questions
Section titled “34.11 Interview Questions”Conceptual Questions
Section titled “Conceptual Questions”-
Q: Explain the difference between L1, L2, and L3 CDK constructs.
- A: L1 constructs are direct CloudFormation resources (CfnBucket, CfnVPC). They mirror CloudFormation exactly. L2 constructs are higher-level with additional defaults, convenience methods, and best practices (Bucket, Vpc). L3 constructs are complete patterns solving specific problems (aws-ecs-patterns.ApplicationLoadBalancedFargateService).
-
Q: How does CDK Pipelines work?
- A: CDK Pipelines are self-mutating: the pipeline stack is defined in CDK, and when it runs, it can update itself based on changes to the CDK code. It uses CodePipeline internally and supports stages, waves, and manual approvals. The pipeline automatically provisions the environment needed to deploy the CDK app.
Scenario-Based Questions
Section titled “Scenario-Based Questions”- Q: Design a multi-account deployment strategy using CDK.
- A: Use CDK Pipelines: define a pipeline in the tools account that deploys to dev/staging/prod accounts using cross-account roles. Use StackSynthesizer for different accounts. Use SSM parameters or Secrets Manager for cross-account secrets. Implement approval gates between environments. Use context flags for environment-specific configurations.
34.12 Exam Tips
Section titled “34.12 Exam Tips” 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 || |+------------------------------------------------------------------+34.13 Summary
Section titled “34.13 Summary” 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