I just finished my No-Nonsense Guide To AWS Cloud Development Kit (CDK). Today, I am going to show you one of the essential AWS CDK building blocks: the Base Stack. So, grab your favorite cup of joe, and let me give you a quick overview.
TLDR: Checkout my GitHub Repo. There are only two classes you need to be worried about,
cdk-base-stack.ts
andcdk-app.ts
.
Table of Contents
๐ฆ Follow me on Twitter if you would like to see more content like this! ๐ฆ
Base Stack
The base stack of a CDK app is where you should put resources that are not going to change, they are stateless. Using this pattern, you can keep your stateful resources (VPC, RDS, DDB, etc) intact while being able to tear down and recreate your stateless (EC2, ECS, S3, etc) resources. Stateless resources can be replaced without the risk of data loss.
In this example, we will be adding a Virtual Private Cloud (VPC) to our base stack. We will be extending a Stack
in this class
. A Stack
should be used to deploy resources independently from the rest of the app resources. Conversely, Constructs
all get deployed together.
Finally, we are going to make our VPC public. Here is a reference to the VPC construct. You can create a public VPC to save costs. Private VPC's contain private subnets which require a NAT Gateway. These incur costs on an hourly basis.
import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2';
export interface CdkBaseStackProps extends cdk.StackProps {
stage: string;
}
export class CdkBaseStack extends cdk.Stack {
private readonly vpc:ec2.Vpc;
constructor(scope: cdk.Construct, id: string,
props?: CdkBaseStackProps) {
super(scope, id, props);
// create a VPC with no private subnets.
// this is for our demo purpose as this will be
// cheaper since you do not need a nat gateway
const vpc = new ec2.Vpc(this, `VPC-${props?.stage}`, {
natGateways:0,
maxAzs: 2,
});
this.vpc = vpc;
}
get stackVpc() : ec2.Vpc{
return this.vpc;
}
}
A couple of notes:
CdkBaseStackProps
is a pattern you can follow to pass parameters yourStack
orConstruct
. I added astage
field to distinguish environments.natGateways:0
- this option ensures there are no private subnets
CDK App
To bring everything together, you can look at our app. I have created a DemoApp
class Construct
. This will be composed of our CdkBaseStack
. You will ultimately end up adding more Construct
s here to provision resources for your cloud application.
import * as cdk from '@aws-cdk/core';
import { Construct } from '@aws-cdk/core';
import { CdkBaseStack, CdkBaseStackProps } from '../lib/cdk-base-stack/cdk-base-stack';
class DemoApp extends Construct{
constructor(scope: cdk.App, id:string){
super(scope,id);
// create a small vpc for the demo
const vpcProps: CdkBaseStackProps = {
stage: id,
description: "Base VPC for AWS Cloud Application",
tags: {env: id},
stackName: `PublicVpcStack-${id}` // used in cloudformation for naming stack
}
const base:CdkBaseStack
= new CdkBaseStack(this, `CdkVpcStack-${id}`,
vpcProps);
}
}
const app = new cdk.App();
new DemoApp(app, 'dev');
A couple of notes here:
const app = new cdk.App();
- this is what initializes our app.new DemoApp(app, 'dev');
- this creates aConstruct
for our app. I am usingdev
as an environment. Once you are happy with thisConstruct
you can simply instantiate aDemoApp
for each environment! This will save you time and money.tags: {env: id}
- tags are very useful and can help you distinguish resources in diff environments. This can come in handy when looking at your billing.
Conclusion
You now have a base class to use when deploying any infrastructure that requires a VPC by using the AWS CDK! As stated before, keep stateful resources (VPC, RDS, DDB, etc) in your base stack since you cannot easily recreate these. Stateless resources (EC2, ECS, S3, etc) can be encapsulated in constructs of their own. Stay tuned! More CDK tutorials to come!
TLDR: Checkout my GitHub Repo. There are only two classes you need to be worried about,
cdk-base-stack.ts
andcdk-app.ts
.
๐ฆ Follow me on Twitter if you would like to see more content like this! ๐ฆ