Skip to content

Commit 82c3646

Browse files
authored
feat(rds): General Purpose gp3 storage volumes for database instance (#22864)
Add support for GP3 storage type. Closes #23036 See https://aws.amazon.com/about-aws/whats-new/2022/11/amazon-rds-general-purpose-gp3-storage-volumes/ ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent bf7586b commit 82c3646

12 files changed

+1909
-7
lines changed

packages/@aws-cdk/aws-rds/README.md

+25-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ new rds.DatabaseClusterFromSnapshot(this, 'Database', {
8181

8282
### Updating the database instances in a cluster
8383

84-
Database cluster instances may be updated in bulk or on a rolling basis.
84+
Database cluster instances may be updated in bulk or on a rolling basis.
8585

8686
An update to all instances in a cluster may cause significant downtime. To reduce the downtime, set the `instanceUpdateBehavior` property in `DatabaseClusterBaseProps` to `InstanceUpdateBehavior.ROLLING`. This adds a dependency between each instance so the update is performed on only one instance at a time.
8787

@@ -188,6 +188,28 @@ Creating a "production" Oracle database instance with option and parameter group
188188

189189
[example of setting up a production oracle instance](test/integ.instance.lit.ts)
190190

191+
Use the `storageType` property to specify the [type of storage](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html)
192+
to use for the instance:
193+
194+
```ts
195+
declare const vpc: ec2.Vpc;
196+
197+
const iopsInstance = new rds.DatabaseInstance(this, 'IopsInstance', {
198+
engine: rds.DatabaseInstanceEngine.mysql({ version: MysqlEngineVersion.VER_8_0_30 }),
199+
vpc,
200+
storageType: rds.StorageType.IO1,
201+
iops: 5000,
202+
});
203+
204+
const gp3Instance = new rds.DatabaseInstance(this, 'Gp3Instance', {
205+
engine: rds.DatabaseInstanceEngine.mysql({ version: MysqlEngineVersion.VER_8_0_30 }),
206+
vpc,
207+
allocatedStorage: 500,
208+
storageType: rds.StorageType.GP3,
209+
storageThroughput: 500, // only applicable for GP3
210+
});
211+
```
212+
191213
## Setting Public Accessibility
192214

193215
You can set public accessibility for the database instance or cluster using the `publiclyAccessible` property.
@@ -737,8 +759,8 @@ To learn more about using the Data API, see the [documentation](https://docs.aws
737759

738760
### Default VPC
739761

740-
The `vpc` parameter is optional.
762+
The `vpc` parameter is optional.
741763

742764
If not provided, the cluster will be created in the default VPC of the account and region.
743-
As this VPC is not deployed with AWS CDK, you can't configure the `vpcSubnets`, `subnetGroup` or `securityGroups` of the Aurora Serverless Cluster.
765+
As this VPC is not deployed with AWS CDK, you can't configure the `vpcSubnets`, `subnetGroup` or `securityGroups` of the Aurora Serverless Cluster.
744766
If you want to provide one of `vpcSubnets`, `subnetGroup` or `securityGroups` parameter, please provide a `vpc`.

packages/@aws-cdk/aws-rds/lib/instance.ts

+63-4
Original file line numberDiff line numberDiff line change
@@ -256,20 +256,42 @@ export interface ProcessorFeatures {
256256

257257
/**
258258
* The type of storage.
259+
*
260+
* @see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html
259261
*/
260262
export enum StorageType {
261263
/**
262264
* Standard.
265+
*
266+
* Amazon RDS supports magnetic storage for backward compatibility. It is recommended to use
267+
* General Purpose SSD or Provisioned IOPS SSD for any new storage needs.
268+
*
269+
* @see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html#CHAP_Storage.Magnetic
263270
*/
264271
STANDARD = 'standard',
265272

266273
/**
267-
* General purpose (SSD).
274+
* General purpose SSD (gp2).
275+
*
276+
* Baseline performance determined by volume size
277+
*
278+
* @see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html#Concepts.Storage.GeneralSSD
268279
*/
269280
GP2 = 'gp2',
270281

282+
/**
283+
* General purpose SSD (gp3).
284+
*
285+
* Performance scales independently from storage
286+
*
287+
* @see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html#Concepts.Storage.GeneralSSD
288+
*/
289+
GP3 = 'gp3',
290+
271291
/**
272292
* Provisioned IOPS (SSD).
293+
*
294+
* @see https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html#USER_PIOPS
273295
*/
274296
IO1 = 'io1'
275297
}
@@ -316,11 +338,27 @@ export interface DatabaseInstanceNewProps {
316338
*/
317339
readonly storageType?: StorageType;
318340

341+
/**
342+
* The storage throughput, specified in mebibytes per second (MiBps).
343+
*
344+
* Only applicable for GP3.
345+
*
346+
* @see https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/CHAP_Storage.html#gp3-storage
347+
*
348+
* @default - 125 MiBps if allocated storage is less than 400 GiB for MariaDB, MySQL, and PostgreSQL,
349+
* less than 200 GiB for Oracle and less than 20 GiB for SQL Server. 500 MiBps otherwise (except for
350+
* SQL Server where the default is always 125 MiBps).
351+
*/
352+
readonly storageThroughput?: number;
353+
319354
/**
320355
* The number of I/O operations per second (IOPS) that the database provisions.
321356
* The value must be equal to or greater than 1000.
322357
*
323-
* @default - no provisioned iops
358+
* @default - no provisioned iops if storage type is not specified. For GP3: 3,000 IOPS if allocated
359+
* storage is less than 400 GiB for MariaDB, MySQL, and PostgreSQL, less than 200 GiB for Oracle and
360+
* less than 20 GiB for SQL Server. 12,000 IOPS otherwise (except for SQL Server where the default is
361+
* always 3,000 IOPS).
324362
*/
325363
readonly iops?: number;
326364

@@ -712,8 +750,16 @@ abstract class DatabaseInstanceNew extends DatabaseInstanceBase implements IData
712750
});
713751
}
714752

715-
const storageType = props.storageType || StorageType.GP2;
716-
const iops = storageType === StorageType.IO1 ? (props.iops || 1000) : undefined;
753+
const storageType = props.storageType ?? StorageType.GP2;
754+
const iops = defaultIops(storageType, props.iops);
755+
if (props.storageThroughput && storageType !== StorageType.GP3) {
756+
throw new Error(`The storage throughput can only be specified with GP3 storage type. Got ${storageType}.`);
757+
}
758+
if (storageType === StorageType.GP3 && props.storageThroughput && iops
759+
&& !Token.isUnresolved(props.storageThroughput) && !Token.isUnresolved(iops)
760+
&& props.storageThroughput/iops > 0.25) {
761+
throw new Error(`The maximum ratio of storage throughput to IOPS is 0.25. Got ${props.storageThroughput/iops}.`);
762+
}
717763

718764
this.cloudwatchLogsExports = props.cloudwatchLogsExports;
719765
this.cloudwatchLogsRetention = props.cloudwatchLogsRetention;
@@ -777,6 +823,7 @@ abstract class DatabaseInstanceNew extends DatabaseInstanceBase implements IData
777823
processorFeatures: props.processorFeatures && renderProcessorFeatures(props.processorFeatures),
778824
publiclyAccessible: props.publiclyAccessible ?? (this.vpcPlacement && this.vpcPlacement.subnetType === ec2.SubnetType.PUBLIC),
779825
storageType,
826+
storageThroughput: props.storageThroughput,
780827
vpcSecurityGroups: securityGroups.map(s => s.securityGroupId),
781828
maxAllocatedStorage: props.maxAllocatedStorage,
782829
domain: this.domainId,
@@ -1234,3 +1281,15 @@ function renderProcessorFeatures(features: ProcessorFeatures): CfnDBInstance.Pro
12341281

12351282
return featuresList.length === 0 ? undefined : featuresList;
12361283
}
1284+
1285+
function defaultIops(storageType: StorageType, iops?: number): number | undefined {
1286+
switch (storageType) {
1287+
case StorageType.STANDARD:
1288+
case StorageType.GP2:
1289+
return undefined;
1290+
case StorageType.GP3:
1291+
return iops;
1292+
case StorageType.IO1:
1293+
return iops ?? 1000;
1294+
}
1295+
}

packages/@aws-cdk/aws-rds/test/instance.test.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,46 @@ describe('instance', () => {
17081708
Engine: 'postgres',
17091709
});
17101710
});
1711+
1712+
test('gp3 storage type', () => {
1713+
new rds.DatabaseInstance(stack, 'Instance', {
1714+
engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_30 }),
1715+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL),
1716+
vpc,
1717+
allocatedStorage: 500,
1718+
storageType: rds.StorageType.GP3,
1719+
storageThroughput: 500,
1720+
iops: 4000,
1721+
});
1722+
1723+
Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBInstance', {
1724+
StorageType: 'gp3',
1725+
StorageThroughput: 500,
1726+
Iops: 4000,
1727+
});
1728+
});
1729+
1730+
test('throws with storage throughput and not GP3', () => {
1731+
expect(() => new rds.DatabaseInstance(stack, 'Instance', {
1732+
engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_30 }),
1733+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL),
1734+
vpc,
1735+
storageType: rds.StorageType.GP2,
1736+
storageThroughput: 500,
1737+
})).toThrow(/storage throughput can only be specified with GP3 storage type/);
1738+
});
1739+
1740+
test('throws with a ratio of storage throughput to IOPS greater than 0.25', () => {
1741+
expect(() => new rds.DatabaseInstance(stack, 'Instance', {
1742+
engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_30 }),
1743+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL),
1744+
vpc,
1745+
allocatedStorage: 1000,
1746+
storageType: rds.StorageType.GP3,
1747+
iops: 5000,
1748+
storageThroughput: 2500,
1749+
})).toThrow(/maximum ratio of storage throughput to IOPS is 0.25/);
1750+
});
17111751
});
17121752

17131753
test.each([
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
5+
"source": {
6+
"path": "InstanceGp3TestDefaultTestDeployAssert21C147A7.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Parameters": {
3+
"BootstrapVersion": {
4+
"Type": "AWS::SSM::Parameter::Value<String>",
5+
"Default": "/cdk-bootstrap/hnb659fds/version",
6+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
7+
}
8+
},
9+
"Rules": {
10+
"CheckBootstrapVersion": {
11+
"Assertions": [
12+
{
13+
"Assert": {
14+
"Fn::Not": [
15+
{
16+
"Fn::Contains": [
17+
[
18+
"1",
19+
"2",
20+
"3",
21+
"4",
22+
"5"
23+
],
24+
{
25+
"Ref": "BootstrapVersion"
26+
}
27+
]
28+
}
29+
]
30+
},
31+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
32+
}
33+
]
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"fcd2d721206458838590e53d084bf2c4ecb08d40f957ba8c2813e1832d5c8aa8": {
5+
"source": {
6+
"path": "cdk-integ-rds-instance-gp3.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "fcd2d721206458838590e53d084bf2c4ecb08d40f957ba8c2813e1832d5c8aa8.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}

0 commit comments

Comments
 (0)