AWS CDK Part 3: How to create an RDS instance

No Comments

Recap

In Part 2 of this blog series we described how to create S3 Buckets and a gateway into our VPC such that traffic will only go via the AWS backbone network. Further, we introduced lifecycle configurations in order to optimize the costs incurred by our S3 Bucket. If you are just beginning to use AWS CDK and want to know how to get started, we recommend you to start reading Part 1 and Part 2. This blog post is part three of our six-part blog series on AWS CDK:

In this blog post we will focus on creating the RDS instance in our architectural setup, running a MySQL database engine, and how to add it to our already existing custom VPC.
cdk-vpc-architecture

Intermezzo

In the previous blogs we assumed the use of CDK version 1.7.0. Due to the ever evolving kit, it is now mandatory to upgrade to a version >= 1.10.0. In order to globally update your version, run the command:

npm update -g aws-cdk

This command will update your CDK tool kit to the latest released version. You can verify your update by running the command:

cdk --version

From this point onward, we assume that you are using CDK version 1.15.0.

The RDS instance

Once again, our point of entry for registering a new stack for our infrastructure is the file ./bin/sample_cdk.ts. Adapt the file to include the following code:

// ./bin/sample_cdk.ts
import 'source-map-support/register';
import cdk = require('@aws-cdk/core');
import {VpcStack} from "../lib/vpc-stack";
import {S3Stack} from "../lib/s3-stack";
import {RdsStack} from "../lib/rds-stack";

const app = new cdk.App();
const vpcStackEntity  = new VpcStack(app, 'VpcStack');
new S3Stack(app, 'S3Stack', {
    vpc: vpcStackEntity.vpc,
    subnetName: vpcStackEntity._subnetName
});
new RdsStack(app, 'RDSStack', {
    vpc: vpcStackEntity.vpc
});
app.synth();

And creating the file ./lib/rds-stack.ts containing the following code:

// ./lib/rds-stack.ts
import {App, Duration, Stack, StackProps} from "@aws-cdk/core";
import {DatabaseInstance, DatabaseInstanceEngine, StorageType} from '@aws-cdk/aws-rds';
import {ISecret, Secret} from '@aws-cdk/aws-secretsmanager';
import {InstanceClass, InstanceSize, InstanceType, Peer, SubnetType, Vpc} from "@aws-cdk/aws-ec2";

export interface RDSStackProps extends StackProps {
    vpc: Vpc;
}

export class RDSStack extends Stack {

    readonly secret: ISecret;
    readonly mySQLRDSInstance: DatabaseInstance;

    constructor(scope: App, id: string, props: RDSStackProps) {
        super(scope, id, props);

    // Place your resource definitions here
    
    }
}

(To install the RDS package, run the command npm i @aws-cdk/aws-rds)

As before, the RDS instance needs to be aware of the VPC we are going to be placing it into. For that purpose we defined a custom RDSStackProps interface within the file ./lib/rds-stack.ts.

Everything is in place now and prepared for the actual RDS instance to be defined. We place the resource definition within our constructor:

this.secret = Secret.fromSecretAttributes(this, 'SamplePassword', {
    secretArn: 'arn:aws:secretsmanager:{region}:{organisation-id}:secret:ImportedSecret-sample',
});

this.mySQLRDSInstance = new DatabaseInstance(this, 'mysql-rds-instance', {
    engine: DatabaseInstanceEngine.MYSQL,
    instanceClass: InstanceType.of(InstanceClass.T2, InstanceSize.SMALL),
    vpc: props.vpc,
    vpcPlacement: {subnetType: SubnetType.ISOLATED},
    storageEncrypted: true,
    multiAz: false,
    autoMinorVersionUpgrade: false,
    allocatedStorage: 25,
    storageType: StorageType.GP2,
    backupRetention: Duration.days(3),
    deletionProtection: false,
    masterUsername: 'Admin',
    databaseName: 'Reporting',
    masterUserPassword: this.secret.secretValue,
    port: 3306
});

All in all this looks quite straightforward, yet, getting to that point was quite a struggle as there is little documentation out there that precisely and in depth describes what configuration properties are needed for what. We found all the properties needed by clicking through the source code of CDK step by step, collecting what was needed, which is one of the advantages of a programmable API.
Just to mention a few decisions that are important for our setup:

    • In terms of our VPC, the property vpcPlacement allows you to decide in which subnet type the RDS instance should be placed. Our architecture provides only two isolated subnets which made our choice quite easy, but in general you might want to consider placing it in a private one if you have your VPC exposed to the public internet.
    • The handling of passwords when programmatically implementing infrastructure is usually quite cumbersome. AWS provides the secrets manager which allows you to store passwords within your AWS cloud and accessing them within your code by arn. This is a handy mechanism that enhances the security of your application and infrastructure since passwords are never hard coded into your program but retrieved at deployment to AWS.
      If you want to find out more on how to add your passwords to the secrets manager you can have a look here.

The rest of the settings are basic database settings and rather self explanatory.

Final build & deploy

We are all set up, and ready to deploy our new CDK stack to our AWS cloud. In Part 1 we have already set up our credentials, so this time we can build and deploy by simply running the following commands:

npm run build && cdk synth

After successfully having synthesised the cloudformation template, you can comfortably check what changed by running the command:

cdk diff --profile sample

Finally, we deploy the changes made to the AWS cloud by running the command

cdk deploy --profile sample

With this deployment we have completed our infrastructure setup. In Cloudformation you can track the progress of your deployment. After successfully creating a VPC, an S3 Bucket and in this blog post a RDS instance, in the following blog post we will tackle the application layer and show you how to implement AWS Lambda functions with CDK and deploy them into our VPC.

Maik Kingma

Maik is a full stack developer, with a focus on backend and the Java / Spring environment. He also has experience in DevOps and is currently aspiring to gather knowledge as a software developer / software architect in the AWS Cloud.

Comment

Your email address will not be published. Required fields are marked *