Skip to content

Commit

Permalink
feat(ec2): gp3 volume iops / throughput validation
Browse files Browse the repository at this point in the history
Adds validation on ec2 and autoscaling volumes to ensure that that the throughput to iops ratio.
  • Loading branch information
csumpter committed Nov 3, 2022
1 parent c0b19b8 commit b61c2b1
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 1 deletion.
13 changes: 12 additions & 1 deletion packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts
Expand Up @@ -2172,16 +2172,27 @@ function synthesizeBlockDeviceMappings(construct: Construct, blockDevices: Block
if (throughput) {
const throughputRange = { Min: 125, Max: 1000 };
const { Min, Max } = throughputRange;

if (volumeType != EbsDeviceVolumeType.GP3) {
throw new Error('throughput property requires volumeType: EbsDeviceVolumeType.GP3');
}

if (throughput < Min || throughput > Max) {
throw new Error(
`throughput property takes a minimum of ${Min} and a maximum of ${Max}`
`throughput property takes a minimum of ${Min} and a maximum of ${Max}`,
);
}

const maximumThroughputRatio = 0.25;
if (iops) {
const iopsRatio = (throughput / iops);
if (iopsRatio > maximumThroughputRatio) {
throw new Error(`Throughput (MiBps) to iops ratio of ${iopsRatio} is too high; maximum is ${maximumThroughputRatio} MiBps per iops`);
}
}
}


if (!iops) {
if (volumeType === EbsDeviceVolumeType.IO1) {
throw new Error('iops property is required with volumeType: EbsDeviceVolumeType.IO1');
Expand Down
21 changes: 21 additions & 0 deletions packages/@aws-cdk/aws-autoscaling/test/auto-scaling-group.test.ts
Expand Up @@ -867,6 +867,27 @@ describe('auto scaling group', () => {
}).toThrow(/throughput property requires volumeType: EbsDeviceVolumeType.GP3/);
});

test('throws if throughput / iops ratio is greater than 0.25', () => {
const stack = new cdk.Stack();
const vpc = mockVpc(stack);
expect(() => {
new autoscaling.AutoScalingGroup(stack, 'MyStack', {
machineImage: new ec2.AmazonLinuxImage(),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.MICRO),
vpc,
maxInstanceLifetime: cdk.Duration.days(0),
blockDevices: [{
deviceName: 'ebs',
volume: autoscaling.BlockDeviceVolume.ebs(15, {
volumeType: autoscaling.EbsDeviceVolumeType.GP3,
throughput: 751,
iops: 3000,
}),
}],
});
}).toThrow('Throughput (MiBps) to iops ratio of 0.25033333333333335 is too high; maximum is 0.25 MiBps per iops');
});

test('can configure instance monitoring', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/volume.ts
Expand Up @@ -713,6 +713,17 @@ export class Volume extends VolumeBase {
if (props.size && (props.iops > maximumRatio * props.size.toGibibytes({ rounding: SizeRoundingBehavior.FAIL }))) {
throw new Error(`\`${volumeType}\` volumes iops has a maximum ratio of ${maximumRatio} IOPS/GiB.`);
}

const maximumThroughputRatios: { [key: string]: number } = {};
maximumThroughputRatios[EbsDeviceVolumeType.GP3] = 0.25;
const maximumThroughputRatio = maximumThroughputRatios[volumeType];
if (props.throughput && props.iops) {
const iopsRatio = (props.throughput / props.iops);
if (iopsRatio > maximumThroughputRatio) {
throw new Error(`Throughput (MiBps) to iops ratio of ${iopsRatio} is too high; maximum is ${maximumThroughputRatio} MiBps per iops`);
}

}
}

if (props.enableMultiAttach) {
Expand Down
13 changes: 13 additions & 0 deletions packages/@aws-cdk/aws-ec2/test/volume.test.ts
Expand Up @@ -1468,4 +1468,17 @@ describe('volume', () => {
}).toThrow(/throughput property requires volumeType: EbsDeviceVolumeType.GP3/);
});

test('Invalid iops to throughput ratio', () => {
const stack = new cdk.Stack();
expect(() => {
new Volume(stack, 'Volume', {
availabilityZone: 'us-east-1a',
size: cdk.Size.gibibytes(125),
volumeType: EbsDeviceVolumeType.GP3,
iops: 3000,
throughput: 751,
});
}).toThrow('Throughput (MiBps) to iops ratio of 0.25033333333333335 is too high; maximum is 0.25 MiBps per iops');
});

});

0 comments on commit b61c2b1

Please sign in to comment.