Storage and volume management in AWS CDK EC2 provides comprehensive control over EBS volumes, block devices, encryption, and device mapping for EC2 instances.
The Volume class creates and manages standalone EBS volumes:
class Volume extends Resource implements IVolume {
constructor(scope: Construct, id: string, props: VolumeProps);
readonly volumeId: string;
readonly availabilityZone: string;
readonly encryptionKey?: kms.IKey;
static fromVolumeAttributes(scope: Construct, id: string, attrs: VolumeAttributes): IVolume;
// IAM permissions for volume operations
grantAttachVolume(grantee: iam.IGrantable, instances?: IInstance[]): iam.Grant;
grantAttachVolumeByResourceTag(grantee: iam.IGrantable, constructs: Construct[]): iam.Grant;
grantDetachVolume(grantee: iam.IGrantable, instances?: IInstance[]): iam.Grant;
grantDetachVolumeByResourceTag(grantee: iam.IGrantable, constructs: Construct[]): iam.Grant;
}
interface IVolume extends IResource {
readonly volumeId: string;
readonly availabilityZone: string;
readonly encryptionKey?: kms.IKey;
grantAttachVolume(grantee: iam.IGrantable, instances?: IInstance[]): iam.Grant;
grantAttachVolumeByResourceTag(grantee: iam.IGrantable, constructs: Construct[]): iam.Grant;
grantDetachVolume(grantee: iam.IGrantable, instances?: IInstance[]): iam.Grant;
grantDetachVolumeByResourceTag(grantee: iam.IGrantable, constructs: Construct[]): iam.Grant;
}
interface VolumeProps {
readonly availabilityZone: string;
readonly size: Size;
readonly volumeType?: VolumeType;
readonly iops?: number;
readonly throughput?: number;
readonly encrypted?: boolean;
readonly encryptionKey?: kms.IKey;
readonly snapshotId?: string;
readonly autoEnableIO?: boolean;
readonly removalPolicy?: RemovalPolicy;
}
interface VolumeAttributes {
readonly volumeId: string;
readonly availabilityZone: string;
readonly encryptionKey?: kms.IKey;
}Enumeration of available EBS volume types:
enum VolumeType {
GENERAL_PURPOSE_SSD = 'gp2',
GENERAL_PURPOSE_SSD_GP3 = 'gp3',
PROVISIONED_IOPS_SSD = 'io1',
PROVISIONED_IOPS_SSD_IO2 = 'io2',
THROUGHPUT_OPTIMIZED_HDD = st1',
COLD_HDD = 'sc1',
MAGNETIC = 'standard'
}
enum EbsDeviceVolumeType {
GENERAL_PURPOSE_SSD = 'gp2',
GENERAL_PURPOSE_SSD_GP3 = 'gp3',
PROVISIONED_IOPS_SSD = 'io1',
PROVISIONED_IOPS_SSD_IO2 = 'io2',
THROUGHPUT_OPTIMIZED_HDD = 'st1',
COLD_HDD = 'sc1',
MAGNETIC = 'standard'
}Class for creating block device mappings:
class BlockDeviceVolume {
static ebs(volumeSize: number, options?: EbsDeviceOptions): BlockDeviceVolume;
static ebsFromSnapshot(snapshotId: string, options?: EbsDeviceSnapshotOptions): BlockDeviceVolume;
static ephemeral(volumeIndex: number): BlockDeviceVolume;
}
interface BlockDevice {
readonly deviceName: string;
readonly volume: BlockDeviceVolume;
readonly mappingEnabled?: boolean;
}
interface EbsDeviceOptions {
readonly encrypted?: boolean;
readonly kmsKey?: kms.IKey;
readonly deleteOnTermination?: boolean;
readonly iops?: number;
readonly throughput?: number;
readonly volumeType?: EbsDeviceVolumeType;
}
interface EbsDeviceSnapshotOptions extends EbsDeviceOptions {
readonly volumeSize?: number;
}import * as ec2 from "@aws-cdk/aws-ec2";
import * as cdk from "@aws-cdk/core";
// Basic EBS volume
const basicVolume = new ec2.Volume(this, "BasicVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(100)
});
// GP3 volume with custom IOPS and throughput
const gp3Volume = new ec2.Volume(this, "GP3Volume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(500),
volumeType: ec2.VolumeType.GENERAL_PURPOSE_SSD_GP3,
iops: 3000,
throughput: 125
});
// IO2 volume for high IOPS workloads
const io2Volume = new ec2.Volume(this, "IO2Volume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(100),
volumeType: ec2.VolumeType.PROVISIONED_IOPS_SSD_IO2,
iops: 10000
});import * as kms from "@aws-cdk/aws-kms";
// Volume with default encryption
const encryptedVolume = new ec2.Volume(this, "EncryptedVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(100),
encrypted: true
});
// Volume with customer-managed KMS key
const kmsKey = new kms.Key(this, "VolumeKey", {
description: "EBS Volume encryption key"
});
const customerEncryptedVolume = new ec2.Volume(this, "CustomerEncryptedVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(200),
encrypted: true,
encryptionKey: kmsKey
});// Volume created from existing snapshot
const snapshotVolume = new ec2.Volume(this, "SnapshotVolume", {
availabilityZone: "us-east-1a",
snapshotId: "snap-12345678",
size: cdk.Size.gibibytes(100)
});const vpc = new ec2.Vpc(this, "MyVpc");
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,
deleteOnTermination: true
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
iops: 3000,
throughput: 125,
encrypted: true
})
},
{
deviceName: "/dev/xvdc",
volume: ec2.BlockDeviceVolume.ebs(500, {
volumeType: ec2.EbsDeviceVolumeType.THROUGHPUT_OPTIMIZED_HDD
})
}
]
});// High IOPS database instance
const databaseInstance = new ec2.Instance(this, "DatabaseInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.XLARGE4),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(1000, {
volumeType: ec2.EbsDeviceVolumeType.PROVISIONED_IOPS_SSD_IO2,
iops: 20000,
encrypted: true
})
}
],
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_NAT
}
});// Create volume from snapshot with specific options
const restoredVolume = ec2.BlockDeviceVolume.ebsFromSnapshot("snap-12345678", {
volumeSize: 200, // Increase size from original snapshot
volumeType: ec2.EbsDeviceVolumeType.GP3,
iops: 3000,
encrypted: true,
deleteOnTermination: false
});
const instanceFromSnapshot = new ec2.Instance(this, "RestoredInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: restoredVolume
}
]
});// Instance with ephemeral (instance store) volumes
const instanceStoreInstance = new ec2.Instance(this, "InstanceStoreInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.I3, ec2.InstanceSize.LARGE),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(50, {
volumeType: ec2.EbsDeviceVolumeType.GP3
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ephemeral(0)
},
{
deviceName: "/dev/xvdc",
volume: ec2.BlockDeviceVolume.ephemeral(1)
}
]
});import * as iam from "@aws-cdk/aws-iam";
const dataVolume = new ec2.Volume(this, "DataVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(500),
volumeType: ec2.VolumeType.GP3
});
const instance = new ec2.Instance(this, "Instance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
machineImage: ec2.MachineImage.latestAmazonLinux(),
availabilityZone: "us-east-1a"
});
// Grant instance permission to attach/detach the volume
dataVolume.grantAttachVolume(instance, [instance]);
dataVolume.grantDetachVolume(instance, [instance]);
// Create IAM role with volume permissions
const volumeRole = new iam.Role(this, "VolumeRole", {
assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com")
});
dataVolume.grantAttachVolume(volumeRole);
dataVolume.grantDetachVolume(volumeRole);// Web server with standard storage
const webInstance = new ec2.Instance(this, "WebInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda", // Root volume
volume: ec2.BlockDeviceVolume.ebs(30, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true
})
},
{
deviceName: "/dev/xvdb", // Application data
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true
})
}
]
});
// Database server with high-performance storage
const dbInstance = new ec2.Instance(this, "DatabaseInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R5, ec2.InstanceSize.XLARGE2),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda", // Root volume
volume: ec2.BlockDeviceVolume.ebs(50, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true
})
},
{
deviceName: "/dev/xvdb", // Database data - high IOPS
volume: ec2.BlockDeviceVolume.ebs(500, {
volumeType: ec2.EbsDeviceVolumeType.PROVISIONED_IOPS_SSD_IO2,
iops: 15000,
encrypted: true
})
},
{
deviceName: "/dev/xvdc", // Database logs - optimized for throughput
volume: ec2.BlockDeviceVolume.ebs(200, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
throughput: 250,
encrypted: true
})
},
{
deviceName: "/dev/xvdd", // Backup storage - cost-optimized
volume: ec2.BlockDeviceVolume.ebs(1000, {
volumeType: ec2.EbsDeviceVolumeType.THROUGHPUT_OPTIMIZED_HDD
})
}
],
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_WITH_NAT
}
});const launchTemplate = new ec2.LaunchTemplate(this, "MyLaunchTemplate", {
machineImage: ec2.MachineImage.latestAmazonLinux(),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(50, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true,
deleteOnTermination: true
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
iops: 3000,
throughput: 125,
encrypted: true,
deleteOnTermination: false // Preserve data volume
})
}
]
});// Import KMS key from another region
const crossRegionKey = kms.Key.fromKeyArn(
this,
"CrossRegionKey",
"arn:aws:kms:us-west-2:123456789012:key/12345678-1234-1234-1234-123456789012"
);
const crossRegionVolume = new ec2.Volume(this, "CrossRegionVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(100),
encrypted: true,
encryptionKey: crossRegionKey
});const managedVolume = new ec2.Volume(this, "ManagedVolume", {
availabilityZone: "us-east-1a",
size: cdk.Size.gibibytes(500),
volumeType: ec2.VolumeType.GP3,
encrypted: true,
removalPolicy: cdk.RemovalPolicy.RETAIN // Prevent accidental deletion
});
// Tag volume for backup automation
cdk.Tags.of(managedVolume).add("Backup", "Daily");
cdk.Tags.of(managedVolume).add("Environment", "Production");// Import existing volume by ID
const existingVolume = ec2.Volume.fromVolumeAttributes(this, "ExistingVolume", {
volumeId: "vol-12345678",
availabilityZone: "us-east-1a"
});
// Import encrypted volume with key
const existingEncryptedVolume = ec2.Volume.fromVolumeAttributes(this, "ExistingEncryptedVolume", {
volumeId: "vol-87654321",
availabilityZone: "us-east-1a",
encryptionKey: kms.Key.fromKeyId(this, "ImportedKey", "alias/my-volume-key")
});// High-throughput workload
const throughputOptimizedInstance = new ec2.Instance(this, "ThroughputInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.D3, ec2.InstanceSize.XLARGE4),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(2000, {
volumeType: ec2.EbsDeviceVolumeType.THROUGHPUT_OPTIMIZED_HDD
})
}
]
});
// Low-latency, high-IOPS workload
const highIopsInstance = new ec2.Instance(this, "HighIopsInstance", {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.I3, ec2.InstanceSize.XLARGE2),
machineImage: ec2.MachineImage.latestAmazonLinux(),
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(100, {
volumeType: ec2.EbsDeviceVolumeType.GP3
})
},
{
deviceName: "/dev/xvdb",
volume: ec2.BlockDeviceVolume.ebs(1000, {
volumeType: ec2.EbsDeviceVolumeType.PROVISIONED_IOPS_SSD_IO2,
iops: 32000
})
}
]
});