Infrastructure as Code (IaC) with AWS CDK (EC2 Example)
June 11, 2026Infrastructure as Code (IaC) is a DevOps approach where infrastructure is defined and managed using code instead of manual setup. This makes environments reproducible, version-controlled, and easy to scale.
In this guide, you'll provision an AWS EC2 instance using the AWS Cloud Development Kit (CDK). CDK lets you define infrastructure in TypeScript (or other languages), synthesize CloudFormation templates, and deploy stacks through the CDK CLI.
Requirements
Before starting, install:
- Node.js version 26
- AWS CDK CLI (
npm i -g aws-cdk) - AWS CLI
AWS Credentials Setup
- Go to IAM → Security credentials in AWS
- Create access keys
- Configure locally:
aws configure
This stores credentials in:
~/.aws/credentials~/.aws/config
CDK requires CloudFormation permissions (and bootstrap-related IAM/S3 access). An IAM user scoped only for Terraform EC2 is often insufficient - attach broader permissions or use a dedicated CDK user.
Project Structure
A simple CDK TypeScript setup:
.├── bin/│ └── app.ts├── lib/│ └── ec2-stack.ts├── cdk.json├── package.json└── tsconfig.json
Install dependencies:
npm i
App Entry
The CDK app wires stacks together in bin/app.ts:
#!/usr/bin/env nodeimport * as cdk from 'aws-cdk-lib';import { Ec2Stack } from '../lib/ec2-stack';const app = new cdk.App();new Ec2Stack(app, 'Ec2Stack', {env: {account: process.env.CDK_DEFAULT_ACCOUNT,region: process.env.CDK_DEFAULT_REGION ?? 'eu-north-1',},instanceName: app.node.tryGetContext('instanceName') ?? 'MyEC2Name',});
Set the target account and region once per shell session:
export CDK_DEFAULT_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)export CDK_DEFAULT_REGION=eu-north-1
On Windows PowerShell:
$env:CDK_DEFAULT_ACCOUNT = aws sts get-caller-identity --query Account --output text$env:CDK_DEFAULT_REGION = "eu-north-1"
Stack and EC2 Instance
Define the stack in lib/ec2-stack.ts:
import * as cdk from 'aws-cdk-lib';import * as ec2 from 'aws-cdk-lib/aws-ec2';import { Construct } from 'constructs';export interface Ec2StackProps extends cdk.StackProps {instanceName?: string;}export class Ec2Stack extends cdk.Stack {constructor(scope: Construct, id: string, props?: Ec2StackProps) {super(scope, id, props);const instanceName = props?.instanceName ?? 'MyEC2Name';const instance = new ec2.Instance(this, 'AppServer', {vpc: ec2.Vpc.fromLookup(this, 'DefaultVpc', { isDefault: true }),instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3,ec2.InstanceSize.MICRO,),machineImage: ec2.MachineImage.latestAmazonLinux2023(),instanceName,});new cdk.CfnOutput(this, 'InstanceId', {value: instance.instanceId,description: 'EC2 instance ID',});new cdk.CfnOutput(this, 'InstancePublicIp', {value: instance.instancePublicIp,description: 'Public IP address',});}}
CDK resolves the default VPC during synthesis. Amazon Linux 2023 is selected automatically for the current region.
Configuration
CDK settings live in cdk.json:
{"app": "npx ts-node --prefer-ts-exts bin/app.ts","context": {"instanceName": "MyEC2Name"}}
Change instanceName in context to override the default tag without editing stack code.
CDK Workflow
Bootstrap the environment (once per account/region):
cdk bootstrap
Preview the CloudFormation template:
cdk synth
Compare deployed stack with local changes:
cdk diff
Deploy the stack:
cdk deploy
Destroy infrastructure:
cdk destroy
Important Notes
- State management
CDK deploys through CloudFormation. Stack state lives in AWS, not in a local file like Terraform's terraform.tfstate.
- Bootstrap stack
The first cdk bootstrap creates an S3 bucket and IAM roles CDK uses for deployments. Keep the bootstrap stack in place while you use CDK in that account/region.
- Idempotency
Running cdk deploy again updates the stack in place when possible instead of recreating resources unnecessarily.
- Version control
Treat CDK code like application code. Commit cdk.json and lockfiles; do not commit cdk.out/ or node_modules/.
Demo
CDK project files for this post live in the cdk-aws-ec2 folder. Get access via code demos.