Use the Conformity Knowledge Base AI to help improve your Cloud Posture

RDS General Purpose SSD

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: RDS-010

Ensure that your Amazon RDS instances are using General Purpose SSDs instead of Provisioned IOPS SSDs for cost-effective storage that fits a broad range of database workloads. Unless you are running mission-critical applications that require more than 10000 IOPS or 160 MiB/s of throughput per database, it is recommended to convert your Provisioned IOPS RDS instances to General Purpose instances in order to lower the cost of your monthly AWS bill while keeping the same I/O performance. For example, if the requirements for your MySQL database are 150GB storage size and 1500 IOPS (input/output operations per second) you can save roughly $110 per month using instances with General Purpose SSD storage instead of ones with Provisioned IOPS SSD storage as the former (1500 IOPS, 150GB storage) costs $234.63/month while the latter (1500 IOPS, 500GB storage) costs only $123.38/month.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Cost
optimisation

Using General Purpose (GP) SSD database storage instead of Provisioned IOPS (PIOPS) SSD storage represents a good strategy for cutting down on Amazon RDS costs because for GP SSDs you only pay for the storage compared to PIOPS SSDs where you pay for both storage and IOPS. Converting existing PIOPS-based databases to GP is often possible by configuring larger storage which gives higher baseline performance of IOPS for a lower cost.


Audit

To determine the storage type configured for your Amazon RDS database instances, perform the following operations:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon RDS console at https://console.aws.amazon.com/rds/.

03 In the navigation panel, under Amazon RDS, choose Databases.

04 Click on the name (link) of the Amazon RDS database instance that you want to examine. To identify RDS database instances, check the resource role available in the Role column (i.e. Instance).

05 Select the Configuration tab and check the Storage type attribute value. If the Storage type attribute value is set to Provisioned IOPS (SSD), the storage type used for the selected Amazon RDS database instance is Provisioned IOPS SSD, therefore the selected database instance is not using the most cost-effective storage type available.

06 Repeat steps no. 4 and 5 for each Amazon RDS database instance available within the current AWS region.

07 Change the AWS cloud region from the navigation bar and repeat the Audit process for other regions.

Using AWS CLI

01 Run describe-db-instances command (OSX/Linux/UNIX) with custom query filters to list the names of the Amazon RDS database instances provisioned in the selected AWS region:

aws rds describe-db-instances
  --region us-east-1
  --output table
  --query 'DBInstances[*].DBInstanceIdentifier'

02 The command output should return a table with the requested database instance names:

--------------------------------
|     DescribeDBInstances      |
+------------------------------+
|  cc-project5-mysql-database  |
|  cc-prod-postgres-database   |
+------------------------------+

03 Run describe-db-instances command (OSX/Linux/UNIX) using the name of the Amazon RDS database instance that you want to examine as the identifier parameter and custom query filters to determine the storage type used for the selected database instance:

aws rds describe-db-instances
  --region us-east-1
  --db-instance-identifier cc-project5-mysql-database
  --query 'DBInstances[*].StorageType'

04 The command output should return the storage type used by the database instance:

[
    "io1"
]

If the describe-db-instances command output returns "io1", as shown in the output example above, the storage type used for the selected Amazon RDS database instance is Provisioned IOPS SSD, therefore the selected database instance is not using the most cost-effective storage type available.

05 Repeat steps no. 3 and 4 for each Amazon RDS database instance available in the selected AWS region.

06 Change the AWS cloud region by updating the --region command parameter value and repeat the Audit process for other regions.

Remediation / Resolution

To change the storage type configured for your Amazon RDS database instances, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Description": "Set Storage Type to General Purpose SSD (gp2)",
	"Parameters": {
		"DBInstanceName": {
			"Default": "mysql-database-instance",
			"Description": "RDS database instance name",
			"Type": "String",
			"MinLength": "1",
			"MaxLength": "63",
			"AllowedPattern": "^[0-9a-zA-Z-/]*$",
			"ConstraintDescription": "Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens."
		},
		"DBInstanceClass": {
				"Default": "db.t2.micro",
				"Description": "DB instance class/type",
				"Type": "String",
				"ConstraintDescription": "Must provide a valid DB instance type."
		},
		"DBAllocatedStorage": {
			"Default": "20",
			"Description": "The size of the database (GiB)",
			"Type": "Number",
			"MinValue": "20",
			"MaxValue": "65536",
			"ConstraintDescription": "Must be between 20 and 65536 GiB."
		},
		"DBName": {
			"Default": "mysqldb",
			"Description": "Database name",
			"Type": "String",
			"MinLength": "1",
			"MaxLength": "64",
			"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
			"ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters."
		},
		"DBUsername": {
			"Description": "Master username for database access",
			"Type": "String",
			"MinLength": "1",
			"MaxLength": "16",
			"AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
			"ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters."
		},
		"DBPassword": {
			"NoEcho": "true",
			"Description": "Password for database access",
			"Type": "String",
			"MinLength": "8",
			"MaxLength": "41",
			"AllowedPattern": "[a-zA-Z0-9]*",
			"ConstraintDescription": "Must contain only alphanumeric characters."
		}
	},
	"Resources": {
		"RDSInstance": {
			"Type": "AWS::RDS::DBInstance",
			"Properties": {
				"DBInstanceIdentifier": {
					"Ref": "DBInstanceName"
				},
				"DBName": {
					"Ref": "DBName"
				},
				"MasterUsername": {
					"Ref": "DBUsername"
				},
				"MasterUserPassword": {
					"Ref": "DBPassword"
				},
				"DBInstanceClass": {
					"Ref": "DBInstanceClass"
				},
				"AllocatedStorage": {
					"Ref": "DBAllocatedStorage"
				},
				"Engine": "MySQL",
				"EngineVersion": "5.7.36",
				"StorageType": "gp2"
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Description: Set Storage Type to General Purpose SSD (gp2)
	Parameters:
		DBInstanceName:
		Default: mysql-database-instance
		Description: RDS database instance name
		Type: String
		MinLength: '1'
		MaxLength: '63'
		AllowedPattern: ^[0-9a-zA-Z-/]*$
		ConstraintDescription: Must begin with a letter and must not end with a hyphen
			or contain two consecutive hyphens.
		DBInstanceClass:
		Default: db.t2.micro
		Description: DB instance class/type
		Type: String
		ConstraintDescription: Must provide a valid DB instance type.
		DBAllocatedStorage:
		Default: '20'
		Description: The size of the database (GiB)
		Type: Number
		MinValue: '20'
		MaxValue: '65536'
		ConstraintDescription: Must be between 20 and 65536 GiB.
		DBName:
		Default: mysqldb
		Description: Database name
		Type: String
		MinLength: '1'
		MaxLength: '64'
		AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
		ConstraintDescription: Must begin with a letter and contain only alphanumeric
			characters.
		DBUsername:
		Description: Master username for database access
		Type: String
		MinLength: '1'
		MaxLength: '16'
		AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
		ConstraintDescription: Must begin with a letter and contain only alphanumeric
			characters.
		DBPassword:
		NoEcho: 'true'
		Description: Password for database access
		Type: String
		MinLength: '8'
		MaxLength: '41'
		AllowedPattern: '[a-zA-Z0-9]*'
		ConstraintDescription: Must contain only alphanumeric characters.
	Resources:
		RDSInstance:
		Type: AWS::RDS::DBInstance
		Properties:
			DBInstanceIdentifier: !Ref 'DBInstanceName'
			DBName: !Ref 'DBName'
			MasterUsername: !Ref 'DBUsername'
			MasterUserPassword: !Ref 'DBPassword'
			DBInstanceClass: !Ref 'DBInstanceClass'
			AllocatedStorage: !Ref 'DBAllocatedStorage'
			Engine: MySQL
			EngineVersion: 5.7.36
			StorageType: gp2

Using Terraform

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 3.27"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_db_instance" "rds-database-instance" {
	engine                = "mysql"
	engine_version        = "5.7"
	instance_class        = "db.t2.micro"
	name                  = "mysqldb"
	username              = "ccmysqluser01"
	password              = "ccmysqluserpwd"
	parameter_group_name  = "default.mysql5.7"

	# Set Storage Type to General Purpose SSD (gp2)
	storage_type          = "gp2"
	allocated_storage     = 150

	apply_immediately = true
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon RDS console at https://console.aws.amazon.com/rds/.

03 In the navigation panel, under Amazon RDS, choose Databases.

04 Select the Amazon RDS database instance that you want to modify, choose Actions, and select Take snapshot.

05 On the Take DB snapshot page, provide a unique name for your new database snapshot in the Snapshot name box, then choose Take snapshot. Once the process is completed, the snapshot status should be set to Available.

06 In the navigation panel, under Amazon RDS, choose Databases.

07 Select the Amazon RDS database instance that you want to reconfigure and choose Modify.

08 On the Modify DB instance: <instance-name> configuration page, perform the following actions:

  1. In the Storage section, select General Purpose (SSD) from the Storage type dropdown list, and enter the instance storage size in GiB required to match the IOPS number previously configured for your instance, in the Allocated storage box.
  2. Choose Continue and review the configuration changes that you want to apply, available in the Summary of modifications section.
  3. In the Scheduling of modifications section, perform one of the following actions based on your workload requirements:
    • Select Apply during the next scheduled maintenance window to apply the changes automatically during the next scheduled maintenance window.
    • Select Apply immediately to apply the changes right away. With this option any pending modifications will be asynchronously applied as soon as possible, regardless of the maintenance window configured for the selected Amazon RDS database instance. Note that any changes available in the pending modifications queue are also applied. If any of the pending modifications require downtime, choosing this option can cause unexpected downtime for your database application.
  4. Choose Modify DB instance to apply the configuration changes.

09 Repeat steps no. 4 – 8 for each Amazon RDS database instance available in the selected AWS region.

10 Change the AWS cloud region from the navigation bar and repeat the Remediation process for other regions.

Using AWS CLI

01 Run create-db-snapshot command (OSX/Linux/UNIX) to take a snapshot of the Amazon RDS database instance that you want to reconfigure:

aws rds create-db-snapshot
  --region us-east-1
  --db-instance-identifier cc-project5-mysql-database
  --db-snapshot-identifier cc-project5-mysql-database-snapshot

02 The command output should return the database instance snapshot metadata:

{
	"DBSnapshot": {
		"MasterUsername": "ccadmin",
		"LicenseModel": "general-public-license",
		"InstanceCreateTime": "2021-05-13T05:45:57.685Z",
		"Engine": "mysql",
		"VpcId": "vpc-abcdabcd",
		"DBSnapshotIdentifier": "cc-project5-mysql-database-snapshot",
		"AllocatedStorage": 100,
		"Status": "creating",
		"PercentProgress": 0,
		"DBSnapshotArn": "arn:aws:rds:us-east-1:123456789012:snapshot:cc-project5-mysql-database-snapshot",
		"EngineVersion": "5.7.30",
		"ProcessorFeatures": [],
		"OptionGroupName": "default:mysql-5-7",
		"AvailabilityZone": "us-east-1a",
		"StorageType": "io1",
		"Encrypted": false,
		"IAMDatabaseAuthenticationEnabled": false,
		"Iops": 1000,
		"DbiResourceId": "db-ABCDABCDABCDABCDABCDABCD",
		"SnapshotType": "manual",
		"Port": 3306,
		"DBInstanceIdentifier": "cc-project5-mysql-database"
	}
}

03 Run modify-db-instance command (OSX/Linux/UNIX) to reconfigure the selected Amazon RDS database instance in order to convert the instance storage type from Provisioned IOPS SSD to General Purpose SSD. Use the --allocated-storage command parameter to set the instance storage size in GB required to match the IOPS number previously set for the selected database instance. The following command request example makes use of --apply-immediately parameter to apply the configuration changes asynchronously and as soon as possible. Any changes available in the pending modifications queue are also applied with this request. If any of the pending modifications require downtime, choosing this option can cause unexpected downtime for your database application. If you skip adding the --apply-immediately parameter to the command request, Amazon RDS will apply your changes during the next maintenance window:

aws rds modify-db-instance
  --region us-east-1
  --db-instance-identifier cc-project5-mysql-database
  --allocated-storage 500
  --storage-type gp2
  --apply-immediately

04 The command output should return the configuration metadata for the modified database instance:

{
	"DBInstance": {
		"PubliclyAccessible": true,
		"MasterUsername": "ccadmin",
		"MonitoringInterval": 0,
		"LicenseModel": "general-public-license",
		"VpcSecurityGroups": [
			{
				"Status": "active",
				"VpcSecurityGroupId": "sg-0abcd1234abcd1234"
			},
			{
				"Status": "active",
				"VpcSecurityGroupId": "sg-abcd1234"
			}
		],
		"InstanceCreateTime": "2021-05-12T08:00:00.677Z",
		"CopyTagsToSnapshot": true,
		"OptionGroupMemberships": [
			{
				"Status": "in-sync",
				"OptionGroupName": "default:mysql-5-7"
			}
		],
		"PendingModifiedValues": {
			"BackupRetentionPeriod": 7
		},        
		"Engine": "mysql",
		"MultiAZ": false,
		"DBSecurityGroups": [],
		"DBParameterGroups": [
			{
				"DBParameterGroupName": "default.mysql5.7",
				"ParameterApplyStatus": "in-sync"
			}
		],
		"PerformanceInsightsEnabled": true,
		"AutoMinorVersionUpgrade": true,
		"PreferredBackupWindow": "06:02-06:32",
		"DBSubnetGroup": {
			"Subnets": [
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-abcd1234",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1d"
					}
				},
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-1234abcd",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1e"
					}
				},
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-abcdabcd",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1b"
					}
				},
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-12341234",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1a"
					}
				},
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-abcd1234",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1f"
					}
				},
				{
					"SubnetStatus": "Active",
					"SubnetIdentifier": "subnet-1234abcd",
					"SubnetOutpost": {},
					"SubnetAvailabilityZone": {
						"Name": "us-east-1c"
					}
				}
			],
			"DBSubnetGroupName": "default-vpc-abcdabcd",
			"VpcId": "vpc-abcdabcd",
			"DBSubnetGroupDescription": "Created from the AWS Management Console",
			"SubnetGroupStatus": "Complete"
		},
		"ReadReplicaDBInstanceIdentifiers": [],
		"AllocatedStorage": 70,
		"DBInstanceArn": "arn:aws:rds:us-east-1:123456789012:db:cc-project5-mysql-database",
		"BackupRetentionPeriod": 0,
		"PreferredMaintenanceWindow": "thu:03:27-thu:03:57",
		"Endpoint": {
			"HostedZoneId": "ABCDABCDABCD",
			"Port": 3306,
			"Address": "cc-project5-mysql-database.abcdabcdabcd.us-east-1.rds.amazonaws.com"
		},
		"DBInstanceStatus": "available",
		"IAMDatabaseAuthenticationEnabled": true,
		"EngineVersion": "5.7.30",
		"DeletionProtection": true,
		"AvailabilityZone": "us-east-1a",
		"DomainMemberships": [],
		"StorageType": "gp2",
		"DbiResourceId": "db-ABCDABCDABCDABCDABCDABCDAB",
		"CACertificateIdentifier": "rds-ca-2019",
		"StorageEncrypted": true,
		"AssociatedRoles": [],
		"DBInstanceClass": "db.t3.medium",
		"DbInstancePort": 0,
		"DBInstanceIdentifier": "cc-project5-mysql-database"
	}
}

05 Repeat steps no. 1 – 4 for each Amazon RDS database instance available in the selected AWS region.

06 Change the AWS cloud region by updating the --region command parameter value and repeat the Remediation process for other regions.

References

Publication date Oct 26, 2016