EC2 instance management in AWS CDK provides comprehensive control over compute resources including instance creation, configuration, instance types, and connections.
The Instance class represents a single EC2 instance with full configuration capabilities:
class Instance extends Resource implements IInstance {
constructor(scope: Construct, id: string, props: InstanceProps);
// Instance identification
readonly instanceId: string;
readonly instanceAvailabilityZone: string;
readonly instancePrivateDnsName: string;
readonly instancePrivateIp: string;
readonly instancePublicDnsName: string;
readonly instancePublicIp: string;
// Security and networking
readonly connections: Connections;
readonly role: IRole;
readonly grantPrincipal: IPrincipal;
// CloudFormation resource
readonly instance: CfnInstance;
readonly osType: OperatingSystemType;
readonly userData: UserData;
// Instance management methods
addSecurityGroup(securityGroup: ISecurityGroup): void;
addToRolePolicy(statement: PolicyStatement): void;
addUserData(...commands: string[]): void;
}
interface InstanceProps {
// Required properties
readonly vpc: IVpc;
readonly instanceType: InstanceType;
readonly machineImage: IMachineImage;
// Optional configuration
readonly keyName?: string;
readonly vpcSubnets?: SubnetSelection;
readonly availabilityZone?: string;
readonly allowAllOutbound?: boolean;
readonly securityGroup?: ISecurityGroup;
readonly instanceName?: string;
readonly role?: IRole;
readonly userData?: UserData;
readonly userDataCausesReplacement?: boolean;
readonly blockDevices?: BlockDevice[];
// CloudFormation init
readonly init?: CloudFormationInit;
readonly initOptions?: ApplyCloudFormationInitOptions;
// Security settings
readonly requireImdsv2?: boolean;
readonly resourceSignalTimeout?: Duration;
}The IInstance interface defines the contract for EC2 instance-like objects:
interface IInstance extends IResource, IConnectable, iam.IGrantable {
readonly instanceId: string;
readonly instanceAvailabilityZone: string;
readonly instancePrivateDnsName: string;
readonly instancePrivateIp: string;
readonly instancePublicDnsName: string;
readonly instancePublicIp: string;
}Instance types define the compute capacity, memory, and network performance:
class InstanceType {
constructor(instanceTypeIdentifier: string);
readonly architecture: InstanceArchitecture;
static of(instanceClass: InstanceClass, instanceSize: InstanceSize): InstanceType;
toString(): string;
}
enum InstanceClass {
// Burstable Performance Instances
T2 = "t2",
T3 = "t3",
T3A = "t3a",
T4G = "t4g",
// General Purpose Instances
M3 = "m3",
M4 = "m4",
M5 = "m5",
M5A = "m5a",
M5AD = "m5ad",
M5D = "m5d",
M5DN = "m5dn",
M5N = "m5n",
M5ZN = "m5zn",
M6A = "m6a",
M6G = "m6g",
M6GD = "m6gd",
M6I = "m6i",
M6ID = "m6id",
// Compute Optimized Instances
C3 = "c3",
C4 = "c4",
C5 = "c5",
C5A = "c5a",
C5AD = "c5ad",
C5D = "c5d",
C5N = "c5n",
C6A = "c6a",
C6G = "c6g",
C6GD = "c6gd",
C6GN = "c6gn",
C6I = "c6i",
C6ID = "c6id",
// Memory Optimized Instances
R3 = "r3",
R4 = "r4",
R5 = "r5",
R5A = "r5a",
R5AD = "r5ad",
R5B = "r5b",
R5D = "r5d",
R5DN = "r5dn",
R5N = "r5n",
R6A = "r6a",
R6G = "r6g",
R6GD = "r6gd",
R6I = "r6i",
R6ID = "r6id",
// Storage Optimized Instances
D2 = "d2",
D3 = "d3",
D3EN = "d3en",
H1 = "h1",
I2 = "i2",
I3 = "i3",
I3EN = "i3en",
I4I = "i4i",
// Accelerated Computing Instances
F1 = "f1",
G3 = "g3",
G4AD = "g4ad",
G4DN = "g4dn",
G5 = "g5",
G5G = "g5g",
P2 = "p2",
P3 = "p3",
P3DN = "p3dn",
P4D = "p4d",
// High Performance Computing
HPC6A = "hpc6a",
// Previous Generation
A1 = "a1",
// And many more...
}
enum InstanceSize {
NANO = "nano",
MICRO = "micro",
SMALL = "small",
MEDIUM = "medium",
LARGE = "large",
XLARGE = "xlarge",
XLARGE2 = "2xlarge",
XLARGE3 = "3xlarge",
XLARGE4 = "4xlarge",
XLARGE6 = "6xlarge",
XLARGE8 = "8xlarge",
XLARGE9 = "9xlarge",
XLARGE10 = "10xlarge",
XLARGE12 = "12xlarge",
XLARGE16 = "16xlarge",
XLARGE18 = "18xlarge",
XLARGE24 = "24xlarge",
XLARGE32 = "32xlarge",
XLARGE48 = "48xlarge",
XLARGE56 = "56xlarge",
XLARGE112 = "112xlarge",
METAL = "metal"
}
enum InstanceArchitecture {
ARM_64 = "arm64",
X86_64 = "x86_64"
}For secure access to private instances, CDK provides a specialized bastion host construct:
class BastionHostLinux extends Resource implements IInstance {
constructor(scope: Construct, id: string, props: BastionHostLinuxProps);
readonly stack: Stack;
readonly connections: Connections;
readonly role: IRole;
readonly grantPrincipal: IPrincipal;
readonly instance: Instance;
// Instance properties
readonly instanceId: string;
readonly instanceAvailabilityZone: string;
readonly instancePrivateDnsName: string;
readonly instancePrivateIp: string;
readonly instancePublicDnsName: string;
readonly instancePublicIp: string;
// Security methods
allowSshAccessFrom(...peer: IPeer[]): void;
}
interface BastionHostLinuxProps {
readonly vpc: IVpc;
readonly availabilityZone?: string;
readonly instanceName?: string;
readonly subnetSelection?: SubnetSelection;
readonly securityGroup?: ISecurityGroup;
readonly instanceType?: InstanceType;
readonly machineImage?: IMachineImage;
readonly blockDevices?: BlockDevice[];
readonly init?: CloudFormationInit;
readonly initOptions?: ApplyCloudFormationInitOptions;
readonly requireImdsv2?: boolean;
}The Connections class manages network connectivity for instances:
class Connections {
constructor(props: ConnectionsProps = {});
readonly connections: Connections;
readonly defaultPort?: Port;
readonly securityGroups: ISecurityGroup[];
// Security group management
addSecurityGroup(...securityGroups: ISecurityGroup[]): void;
// Outbound connections
allowTo(other: IConnectable, portRange: Port, description?: string): void;
allowToAnyIpv4(portRange: Port, description?: string): void;
allowToDefaultPort(other: IConnectable, description?: string): void;
allowDefaultPortTo(other: IConnectable, description?: string): void;
// Inbound connections
allowFrom(other: IConnectable, portRange: Port, description?: string): void;
allowFromAnyIpv4(portRange: Port, description?: string): void;
allowDefaultPortFrom(other: IConnectable, description?: string): void;
allowDefaultPortFromAnyIpv4(description?: string): void;
// Internal connections
allowInternally(portRange: Port, description?: string): void;
allowDefaultPortInternally(description?: string): void;
}
interface ConnectionsProps {
readonly peer?: IPeer;
readonly securityGroups?: ISecurityGroup[];
readonly defaultPort?: Port;
}
interface IConnectable {
readonly connections: Connections;
}import * as ec2 from "@aws-cdk/aws-ec2";
import * as iam from "@aws-cdk/aws-iam";
const vpc = new ec2.Vpc(this, "MyVpc");
const instance = new ec2.Instance(this, "MyInstance", {
vpc,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
machineImage: ec2.MachineImage.latestAmazonLinux(),
keyName: "my-key-pair"
});const role = new iam.Role(this, "InstanceRole", {
assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore")
]
});
const securityGroup = new ec2.SecurityGroup(this, "InstanceSG", {
vpc,
description: "Security group for web server",
allowAllOutbound: true
});
securityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
"Allow HTTP traffic"
);
const userData = ec2.UserData.forLinux();
userData.addCommands(
"yum update -y",
"yum install -y httpd",
"systemctl start httpd",
"systemctl enable httpd"
);
const instance = new ec2.Instance(this, "WebServer", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL),
machineImage: ec2.MachineImage.latestAmazonLinux(),
securityGroup,
role,
userData,
vpcSubnets: {
subnetType: ec2.SubnetType.PUBLIC
}
});const instance = new ec2.Instance(this, "InstanceWithStorage", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.LARGE),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(50, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
iops: 3000,
throughput: 125
})
}
]
});const bastion = new ec2.BastionHostLinux(this, "BastionHost", {
vpc,
subnetSelection: {
subnetType: ec2.SubnetType.PUBLIC
},
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO)
});
// Allow SSH access from specific IP ranges
bastion.allowSshAccessFrom(ec2.Peer.ipv4("203.0.113.0/24"));
// Allow bastion to connect to private instances
bastion.connections.allowTo(
privateInstance,
ec2.Port.tcp(22),
"SSH access to private instance"
);const init = ec2.CloudFormationInit.fromElements(
ec2.InitConfig.fromElements(
ec2.InitPackage.yum("httpd"),
ec2.InitService.enable("httpd", {
enabled: true,
ensureRunning: true
}),
ec2.InitFile.fromString("/var/www/html/index.html", "<h1>Hello World</h1>")
)
);
const instance = new ec2.Instance(this, "ConfiguredInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux(),
init,
initOptions: {
timeout: cdk.Duration.minutes(10),
includeUrl: true,
includeRole: true,
printLog: true
}
});// Burstable performance instance for development
const devInstance = new ec2.Instance(this, "DevInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux()
});
// Compute optimized instance for CPU-intensive workloads
const computeInstance = new ec2.Instance(this, "ComputeInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.C5, ec2.InstanceSize.XLARGE),
machineImage: ec2.MachineImage.latestAmazonLinux()
});
// Memory optimized instance for in-memory databases
const memoryInstance = new ec2.Instance(this, "MemoryInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.XLARGE2),
machineImage: ec2.MachineImage.latestAmazonLinux()
});const secureInstance = new ec2.Instance(this, "SecureInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
machineImage: ec2.MachineImage.latestAmazonLinux(),
requireImdsv2: true // Require IMDSv2 for security
});const webServer = new ec2.Instance(this, "WebServer", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL),
machineImage: ec2.MachineImage.latestAmazonLinux()
});
const database = new ec2.Instance(this, "Database", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.LARGE),
machineImage: ec2.MachineImage.latestAmazonLinux(),
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_NAT
}
});
// Allow web server to connect to database
webServer.connections.allowTo(
database,
ec2.Port.tcp(3306),
"Database connection"
);
// Allow SSH access from bastion to both instances
bastion.connections.allowTo(webServer, ec2.Port.tcp(22));
bastion.connections.allowTo(database, ec2.Port.tcp(22));