Last updated: Jan 26, 2024
Reading timeยท5 min
To specify what subnet we want to provision our resources in, we have to use one of the following 3 props that achieve the same goal:
subnetSelection
subnets
vpcSubnets
If we don't explicitly select a subnet to launch our instances in, the default behavior is for them to be launched in private subnets.
Let's look at a complete example where we create:
import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = new ec2.Vpc(this, 'my-cdk-vpc', { ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), natGateways: 0, maxAzs: 3, subnetConfiguration: [ { name: 'public-subnet-1', subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24, }, { name: 'isolated-subnet-1', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 28, }, ], }); const securityGroup = new ec2.SecurityGroup(this, 'security-group-id', { vpc, }); const webServer = new ec2.Instance(this, 'web-server', { instanceType: ec2.InstanceType.of( ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO, ), machineImage: ec2.MachineImage.latestAmazonLinux2(), vpc, securityGroup, // ๐ set the subnet type to PUBLIC vpcSubnets: {subnetType: ec2.SubnetType.PUBLIC}, }); } }
Let's go over what we did in the code sample.
We created a VPC that has a PUBLIC
and a PRIVATE_ISOLATED
subnet groups.
This subnetConfiguration
will create a total of 6 subnets because we've set
the maxAzs
prop to 3
. Each subnet group creates a subnet in every
availability zone.
We created a Security Group, which we will associate with our EC2 instance
We created an EC2 instance, for which we explicitly selected a subnet type
by passing the vpcSubnets
prop. The EC2 instance will be launched in one
of the 3 PUBLIC
subnets we created (because maxAzs
of the VPC is 3).
The subnetType
prop selects all subnets of the given type, in our case all
PUBLIC
subnets.
I'll deploy the stack by running:
npx aws-cdk deploy
If we take a look at the provisioned EC2 instance in the EC2 management console,
we can see that it was provisioned in one of the PUBLIC
subnets:
If we had more than 1 subnet group of type PUBLIC
, we would have to narrow
them down using the subnetGroupName
property.
const webServer = new ec2.Instance(this, 'web-server', { instanceType: ec2.InstanceType.of( ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO, ), machineImage: ec2.MachineImage.latestAmazonLinux2(), vpc, securityGroup, // ๐ launch in subnet with a specific Group Name vpcSubnets: {subnetGroupName: 'public-subnet-1'}, })
By using the subnetGroupName
property, we are able to select a specific subnet
group by name, in case we have provisioned a VPC with multiple subnet groups of
the same type.
We are also able to select a subnet in a specific availability zone.
Subnet groups create the specific subnet type in multiple availability zones, so we also have the option to select a specific subnet in a specific availability zone:
const webServer = new ec2.Instance(this, 'web-server', { instanceType: ec2.InstanceType.of( ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO, ), machineImage: ec2.MachineImage.latestAmazonLinux2(), vpc, securityGroup, // ๐ explicitly pick availability zones of the subnet vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC, availabilityZones: [cdk.Stack.of(this).availabilityZones[0]], }, });
We selected a PUBLIC
subnet in one particular availability zone for our EC2
instance to be launched in.
Selecting the specific availability zone of the subnet only works for stacks that aren't environment-agnostic (account and region are explicitly set).
To delete the provisioned resources, issue the destroy
command:
npx aws-cdk destroy
I've also written an article on how to provision and configure an EC2 instance.
We'll look at an example of how we can add tags to subnets in AWS CDK.
Especially useful is the Name
tag, which helps us distinguish between
resources in the VPC management console.
Let's look at an example where we:
PUBLIC
and
PRIVATE_ISOLATED
import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ๐ create VPC const vpc = new ec2.Vpc(this, 'my-cdk-vpc', { ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), natGateways: 0, maxAzs: 3, subnetConfiguration: [ { name: 'public-subnet-1', subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24, }, { name: 'isolated-subnet-1', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 28, }, ], }); // ๐ define function that tags subnets const tagAllSubnets = ( subnets: ec2.ISubnet[], tagName: string, tagValue: string, ) => { for (const subnet of subnets) { cdk.Tags.of(subnet).add( tagName, `${tagValue}-${subnet.availabilityZone}`, ); } }; // ๐ tag subnets const {stackName} = cdk.Stack.of(this); tagAllSubnets(vpc.publicSubnets, 'Name', `${stackName}/public`); tagAllSubnets(vpc.isolatedSubnets, 'Name', `${stackName}/isolated`); tagAllSubnets(vpc.publicSubnets, 'env', 'staging'); tagAllSubnets(vpc.isolatedSubnets, 'env', 'dev'); } }
Let's go over the code snippet.
PUBLIC
and 1
PRIVATE_ISOLATED
. Because we set the maxAzs
prop to 3, this configuration
will create a total of 6 subnets. Each subnet group creates a subnet in every
availability zone.tagAllSubnets
function that takes 3 parameters:subnets
- an array of subnets to tag
tagName
- the name of the tag to apply on the subnets in the array
tagValue
- the value of the tag
You would have to customize this function to the tagging conventions your organization follows.
tagAllSubnets
function to add Name
and env
tags to our
subnets. The Name
of a subnet is now going to look like
cdk-stack/public-us-east-1a
.Let's provision the resources:
npx aws-cdk deploy
After a successful deployment, we can see that the Name
tags have been applied
to the subnets.
Each subnet is associated with a route table, so the subnet tags also got applied to the route tables:
The only route table that didn't get tagged is the main one, which has no subnet associations.
The complete tag section of a subnet shows both of the tags we have added -
Name
and env
:
To delete the resources we have provisioned, run the destroy
command:
npx aws-cdk destroy
If you'd like to read more on using tags in AWS CDK, check out the following article.
You can learn more about the related topics by checking out the following tutorials: