Chapter 5: AWS CDK Basics
Chapter 5: AWS CDK Basics
Chapter Overview
This chapter will introduce the basic concepts, installation, and configuration methods of the AWS Cloud Development Kit (CDK), as well as how to use the Python SDK for basic development. CDK is an Infrastructure as Code (IaC) tool provided by AWS that allows you to define cloud resources using familiar programming languages.
Learning Objectives
- Understand the core concepts and architecture of AWS CDK
- Master the installation and configuration process of CDK
- Learn to use the Python CDK SDK for basic development
- Understand the CDK project structure and best practices
- Be able to create and deploy your first CDK application
5.1 AWS CDK Overview
5.1.1 What is AWS CDK
The AWS Cloud Development Kit (CDK) is an open-source software development framework for defining cloud infrastructure using familiar programming languages. CDK compiles your code into CloudFormation templates.
Advantages of CDK
- Infrastructure as Code: Use familiar programming languages
- IDE Support: Full autocompletion and type checking
- Component Reusability: Reuse code through functions and classes
- High-level Abstractions: Provides high-level constructs to simplify complex configurations
5.1.2 Core Concepts of CDK
Concept | Description | Example |
---|---|---|
App | The root of a CDK application, containing one or more Stacks | cdk.App() |
Stack | A unit of deployment, corresponding to a CloudFormation template | MyStack(app, "MyStack") |
Construct | A basic building block, representing a cloud component | aws_lambda.Function() |
Resource | The lowest-level construct, directly mapping to a CloudFormation resource | CfnFunction |
5.1.3 CDK Architecture Model
Three-layer Architecture
- L1 Constructs: Direct mapping of CloudFormation resources
- L2 Constructs: High-level constructs with reasonable defaults
- L3 Constructs: Pattern constructs that implement common architectural patterns
5.2 Environment Setup and Installation
5.2.1 Prerequisites
# Check Node.js version (required for CDK CLI)
node --version # Requires >= 14.x
# Check Python version
python --version # Recommended >= 3.8
# Check AWS CLI configuration
aws configure list
5.2.2 Installing the CDK CLI
# Install the CDK CLI globally
npm install -g aws-cdk
# Verify the installation
cdk --version
# Initialize the CDK environment (for first-time use)
cdk bootstrap
Important Reminder
cdk bootstrap
creates necessary resources in your AWS account (S3 bucket, IAM roles, etc.) and only needs to be run once per region.
5.2.3 Creating a Python CDK Project
# Create a new CDK project
mkdir my-lambda-cdk
cd my-lambda-cdk
# Initialize a Python CDK project
cdk init app --language python
# Activate the virtual environment
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate.bat # Windows
# Install dependencies
pip install -r requirements.txt
5.2.4 Project Structure Analysis
my-lambda-cdk/
├── app.py # CDK application entry point
├── my_lambda_cdk/ # Main code directory
│ ├── __init__.py
│ └── my_lambda_cdk_stack.py # Stack definition
├── tests/ # Test directory
├── requirements.txt # Python dependencies
├── cdk.json # CDK configuration file
└── .venv/ # Virtual environment
5.3 Python CDK SDK Basics
5.3.1 Basic Imports and Setup
# app.py
import aws_cdk as cdk
from my_lambda_cdk.my_lambda_cdk_stack import MyLambdaCdkStack
app = cdk.App()
MyLambdaCdkStack(app, "MyLambdaCdkStack",
env=cdk.Environment(
account='123456789012', # Replace with your account ID
region='us-east-1' # Replace with your region
)
)
app.synth()
5.3.2 Basic Stack Structure
# my_lambda_cdk/my_lambda_cdk_stack.py
from aws_cdk import (
Stack,
aws_lambda as _lambda,
aws_iam as iam,
Duration,
CfnOutput
)
from constructs import Construct
class MyLambdaCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Define your resources here
self.create_lambda_function()
def create_lambda_function(self):
"""Example method for creating a Lambda function"""
# This will be implemented in subsequent chapters
pass
5.3.3 Common CDK Patterns
Resource Naming Conventions
class MyLambdaCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Use consistent naming conventions
self.lambda_function = self._create_lambda_function()
self.api_gateway = self._create_api_gateway()
def _create_lambda_function(self):
"""Private method to create a Lambda function"""
return _lambda.Function(
self, "MyFunction", # Construct ID
# Configuration parameters...
)
Environment Variables and Configuration
import os
from aws_cdk import aws_lambda as _lambda
# Get configuration from environment variables
ENVIRONMENT = os.getenv('ENVIRONMENT', 'dev')
REGION = os.getenv('AWS_REGION', 'us-east-1')
class MyLambdaCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Environment-based resource naming
function_name = f"my-function-{ENVIRONMENT}"
self.lambda_function = _lambda.Function(
self, "MyFunction",
function_name=function_name,
# Other configurations...
)
5.4 CDK Command-line Tool
5.4.1 Common CDK Commands
Command | Function | Example |
---|---|---|
cdk list | List all Stacks | cdk list |
cdk synth | Synthesize a CloudFormation template | cdk synth MyStack |
cdk diff | Show differences from the deployed version | cdk diff MyStack |
cdk deploy | Deploy a Stack | cdk deploy MyStack |
cdk destroy | Delete a Stack | cdk destroy MyStack |
5.4.2 Development Workflow
# 1. After developing the code, first check the syntax
python -m py_compile my_lambda_cdk/*.py
# 2. Synthesize the template for checking
cdk synth
# 3. View changes
cdk diff
# 4. Deploy to the development environment
cdk deploy --profile dev
# 5. After testing is complete, deploy to the production environment
cdk deploy --profile prod
5.4.3 Debugging and Troubleshooting
# Enable debug mode
import aws_cdk as cdk
app = cdk.App()
# Add tags for resource management
cdk.Tags.of(app).add("Project", "MyLambdaProject")
cdk.Tags.of(app).add("Environment", "Development")
# Output important information
class MyLambdaCdkStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Create resources...
# Output useful information
CfnOutput(self, "LambdaFunctionArn",
value=self.lambda_function.function_arn,
description="Lambda Function ARN")
5.5 CDK Best Practices
5.5.1 Project Organization
# Recommended project structure
my_lambda_cdk/
├── stacks/ # Stack definitions
│ ├── __init__.py
│ ├── lambda_stack.py # Lambda-related resources
│ ├── api_stack.py # API Gateway related
│ └── database_stack.py # Database related
├── constructs/ # Custom constructs
│ ├── __init__.py
│ └── lambda_construct.py
├── lambda_functions/ # Lambda function code
│ ├── function1/
│ └── function2/
└── tests/ # Test code
5.5.2 Configuration Management
# config.py
import os
from dataclasses import dataclass
from typing import Dict, Any
@dataclass
class EnvironmentConfig:
environment: str
lambda_memory: int
lambda_timeout: int
log_level: str
@classmethod
def from_environment(cls) -> 'EnvironmentConfig':
env = os.getenv('ENVIRONMENT', 'dev')
configs = {
'dev': cls(
environment='dev',
lambda_memory=128,
lambda_timeout=30,
log_level='DEBUG'
),
'prod': cls(
environment='prod',
lambda_memory=256,
lambda_timeout=60,
log_level='INFO'
)
}
return configs.get(env, configs['dev'])
5.5.3 Security Best Practices
Security Notes
- Never hard-code sensitive information in your code
- Use AWS Secrets Manager or Parameter Store to store secrets
- Follow the principle of least privilege
- Regularly review IAM permissions
from aws_cdk import aws_secretsmanager as secretsmanager
class SecureStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Create a secret
db_secret = secretsmanager.Secret(
self, "DatabaseSecret",
description="Database credentials",
generate_secret_string=secretsmanager.SecretStringGenerator(
secret_string_template='{"username": "admin"}',
generate_string_key="password",
exclude_characters=" %+~`#$&*()|[]{}:;<>?!'/\\\"",
password_length=32
)
)
# Use the secret in a Lambda function
lambda_function = _lambda.Function(
self, "SecureFunction",
# ... other configurations
environment={
"DB_SECRET_ARN": db_secret.secret_arn
}
)
# Grant the Lambda function permission to access the secret
db_secret.grant_read(lambda_function)
5.6 Hands-on Practice
5.6.1 Creating Your First CDK Application
Create a simple CDK application with a basic Stack structure:
# exercises/basic_app.py
import aws_cdk as cdk
from aws_cdk import Stack
from constructs import Construct
class BasicStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# Add tags
cdk.Tags.of(self).add("Project", "CDK-Learning")
# Output Stack information
cdk.CfnOutput(self, "StackName",
value=self.stack_name,
description="The name of this stack")
app = cdk.App()
BasicStack(app, "BasicStack")
app.synth()
5.6.2 Exercises
- Basic Exercise: Create a CDK project with two Stacks
- Intermediate Exercise: Implement configuration management to support different environments
- Advanced Exercise: Create a custom Construct to encapsulate common functionality
5.7 Chapter Summary
Key Takeaways
- CDK is a powerful tool for defining AWS infrastructure using code
- The Python CDK provides full type support and IDE integration
- Following best practices can improve code quality and maintainability
- Security should be considered from the beginning of a project
In the next chapter, we will learn how to use CDK to create and deploy Lambda functions, including function configuration, permission management, and deployment strategies.