Ir al contenido

AWS CDK Cheat Sheet

Overview

AWS Cloud Development Kit (CDK) is an open-source software development framework that allows you to define cloud infrastructure using familiar programming languages. Instead of writing declarative JSON or YAML templates, you use TypeScript, Python, Java, C#, or Go to create reusable infrastructure components called constructs. CDK synthesizes your code into AWS CloudFormation templates, giving you the full power of a programming language—loops, conditionals, abstractions—while maintaining the safety and repeatability of infrastructure as code.

CDK operates on three levels of constructs: L1 (CloudFormation resources mapped 1:1), L2 (higher-level abstractions with sensible defaults and helper methods), and L3 (patterns that combine multiple resources into common architectures). The Construct Library provides hundreds of pre-built L2 and L3 constructs covering most AWS services. CDK also includes the CDK Pipelines module for self-mutating CI/CD pipelines and integrates with tools like cdk-nag for policy validation and compliance checking.

Installation

Install CDK CLI

# Install globally via npm
npm install -g aws-cdk

# Verify installation
cdk --version

# Install specific version
npm install -g aws-cdk@2.150.0

Initialize a New Project

# TypeScript project
cdk init app --language typescript

# Python project
cdk init app --language python
source .venv/bin/activate
pip install -r requirements.txt

# Go project
cdk init app --language go

Bootstrap Your AWS Account

# Bootstrap default account/region
cdk bootstrap

# Bootstrap specific account and region
cdk bootstrap aws://123456789012/us-east-1

# Bootstrap with custom qualifier
cdk bootstrap --qualifier myapp --toolkit-stack-name CDKToolkit-myapp

# Bootstrap multiple regions
cdk bootstrap aws://123456789012/us-east-1 aws://123456789012/eu-west-1

# Bootstrap with execution policies
cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::policy/AdministratorAccess"

Core Commands

CommandDescription
cdk initCreate a new CDK project from template
cdk synthSynthesize CloudFormation template
cdk deployDeploy stack to AWS
cdk destroyDelete deployed stack
cdk diffCompare deployed stack with local changes
cdk lsList all stacks in the app
cdk bootstrapPrepare AWS account for CDK deployments
cdk watchWatch for file changes and auto-deploy
cdk doctorDiagnose CDK environment issues
cdk contextManage cached context values

Synthesize and Deploy

# Synthesize all stacks
cdk synth

# Synthesize specific stack
cdk synth MyStack

# Deploy all stacks
cdk deploy --all

# Deploy specific stack with auto-approve
cdk deploy MyStack --require-approval never

# Deploy with parameters
cdk deploy --parameters MyStack:BucketName=my-bucket

# Deploy with context values
cdk deploy -c environment=production

# Hot-swap deploy for faster iteration (dev only)
cdk deploy --hotswap

# Watch mode for continuous deployment
cdk watch

Diff and Inspection

# Show differences between deployed and local
cdk diff

# Diff specific stack
cdk diff MyStack

# Show synthesized template
cdk synth MyStack --json

# List stacks
cdk ls

# Show context values
cdk context
cdk context --reset

Stack Definition (TypeScript)

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';

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

    // DynamoDB table
    const table = new dynamodb.Table(this, 'ItemsTable', {
      partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
      billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Lambda function
    const fn = new lambda.Function(this, 'Handler', {
      runtime: lambda.Runtime.NODEJS_20_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'index.handler',
      environment: {
        TABLE_NAME: table.tableName,
      },
    });

    // Grant Lambda read/write to DynamoDB
    table.grantReadWriteData(fn);

    // API Gateway
    const api = new apigateway.RestApi(this, 'Api', {
      restApiName: 'My Service',
    });
    api.root.addResource('items').addMethod('GET', new apigateway.LambdaIntegration(fn));

    // Outputs
    new cdk.CfnOutput(this, 'ApiUrl', { value: api.url });
  }
}

Stack Definition (Python)

from aws_cdk import (
    Stack, RemovalPolicy, CfnOutput,
    aws_s3 as s3,
    aws_lambda as _lambda,
    aws_dynamodb as dynamodb,
)
from constructs import Construct

class MyServiceStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        bucket = s3.Bucket(self, "DataBucket",
            versioned=True,
            removal_policy=RemovalPolicy.DESTROY,
            auto_delete_objects=True,
        )

        fn = _lambda.Function(self, "Processor",
            runtime=_lambda.Runtime.PYTHON_3_12,
            code=_lambda.Code.from_asset("lambda"),
            handler="handler.main",
            environment={"BUCKET": bucket.bucket_name},
        )

        bucket.grant_read_write(fn)

        CfnOutput(self, "BucketName", value=bucket.bucket_name)

Configuration

cdk.json

{
  "app": "npx ts-node --prefer-ts-exts bin/my-app.ts",
  "watch": {
    "include": ["**"],
    "exclude": [
      "README.md", "cdk*.json", "**/*.d.ts", "**/*.js",
      "tsconfig.json", "package*.json", "yarn.lock", "node_modules", "test"
    ]
  },
  "context": {
    "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
    "@aws-cdk/core:stackRelativeExports": true,
    "environment": "development"
  }
}

Environment-Specific Stacks

const app = new cdk.App();
const env = app.node.tryGetContext('environment') || 'dev';

new MyServiceStack(app, `MyService-${env}`, {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION,
  },
});

Advanced Usage

Custom Constructs

export class SecureBucket extends Construct {
  public readonly bucket: s3.Bucket;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    this.bucket = new s3.Bucket(this, 'Bucket', {
      encryption: s3.BucketEncryption.S3_MANAGED,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      enforceSSL: true,
      versioned: true,
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });
  }
}

CDK Pipelines

import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';

const pipeline = new CodePipeline(this, 'Pipeline', {
  pipelineName: 'MyPipeline',
  synth: new ShellStep('Synth', {
    input: CodePipelineSource.gitHub('owner/repo', 'main'),
    commands: ['npm ci', 'npm run build', 'npx cdk synth'],
  }),
});

pipeline.addStage(new MyAppStage(this, 'Prod', {
  env: { account: '123456789012', region: 'us-east-1' },
}));

Aspects for Policy Enforcement

import * as cdk from 'aws-cdk-lib';
import { IConstruct } from 'constructs';

class BucketEncryptionChecker implements cdk.IAspect {
  visit(node: IConstruct): void {
    if (node instanceof s3.CfnBucket) {
      if (!node.bucketEncryption) {
        cdk.Annotations.of(node).addError('Bucket must have encryption enabled');
      }
    }
  }
}

cdk.Aspects.of(app).add(new BucketEncryptionChecker());

Testing

import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { MyServiceStack } from '../lib/my-service-stack';

test('DynamoDB Table Created', () => {
  const app = new cdk.App();
  const stack = new MyServiceStack(app, 'TestStack');
  const template = Template.fromStack(stack);

  template.hasResourceProperties('AWS::DynamoDB::Table', {
    BillingMode: 'PAY_PER_REQUEST',
  });

  template.resourceCountIs('AWS::Lambda::Function', 1);
});

Troubleshooting

IssueSolution
cdk bootstrap fails with access deniedEnsure IAM user has cloudformation:* and s3:* permissions
--hotswap not updating LambdaHot-swap only works for code changes, not config changes
Context value not foundRun cdk context --reset and re-synth
Stack stuck in ROLLBACK_COMPLETEDelete the stack manually in CloudFormation console, then redeploy
Cannot find module 'constructs'Run npm install — constructs is a peer dependency in CDK v2
Circular dependency between stacksUse CfnOutput and Fn.importValue or restructure into a single stack
Synth produces empty templateEnsure stacks are instantiated in bin/ entry point