AWS CFN - Create VPC and subnets
This is a fundamental example of creating AWS VPC and the subnets using AWS Cloudformation(CFN). In the next post, I’ve discussed the AWS CFN - Create IGW and NAT.
The prerequisite for this post is AWS Cloudformation to create AWS VPC.
Here is the CFN YAML to create the above architecture. Please visit the reference1 I used to create this post if you want more information. As shown in the above diagram x.y
prefix (at line# 4), you must pass the parameter as --parameters ParameterKey=VpcCidrPrefix,ParameterValue=10.0
when you are creating the stack.
AWSTemplateFormatVersion: "2010-09-09"
Description: My VPC example
Parameters:
VpcCidrPrefix:
Description: prefix for the CIDER
Type: String
AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})"
Resources:
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Join [ "", [!Ref VpcCidrPrefix, ".0.0/21"]]
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Ref AWS::StackName
subnetDmzA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".0.0/24"]]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: DEV-DMZ A
- Key: Scope
Value: public
VpcId: !Ref Vpc
subnetDmzB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".1.0/24"]]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: DEV-DMZ B
- Key: Scope
Value: public
VpcId: !Ref Vpc
subnetDmzC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".2.0/24"]]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: DEV-DMZ C
- Key: Scope
Value: public
VpcId: !Ref Vpc
subnetAppA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".3.0/24"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-APP B
- Key: Scope
Value: private
VpcId: !Ref Vpc
subnetAppB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".4.0/24"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-APP B
- Key: Scope
Value: private
VpcId: !Ref Vpc
subnetAppC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".5.0/24"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-APP C
- Key: Scope
Value: private
VpcId: !Ref Vpc
subnetDbA:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".6.0/28"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-DB A
- Key: Scope
Value: private
VpcId: !Ref Vpc
subnetDbB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".6.16/28"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-DB B
- Key: Scope
Value: private
VpcId: !Ref Vpc
subnetDbC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [2, !GetAZs ""]
CidrBlock: !Join ["", [!Ref VpcCidrPrefix, ".6.32/28"]]
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: DEV-DB C
- Key: Scope
Value: private
VpcId: !Ref Vpc
Outputs:
VpcId:
Description: "VPC ID"
Value: !Ref Vpc
Export:
Name: !Sub ${AWS::StackName}-VpcId
VpcCidr:
Description: "VPC ID"
Value: !GetAtt Vpc.CidrBlock
Export:
Name: !Sub ${AWS::StackName}-VpcCidr
DmzSubnetAId:
Description: "DMZ A subnet ID"
Value: !Ref subnetDmzA
Export:
Name: !Sub ${AWS::StackName}-DmzSubnetAId
DmzSubnetBId:
Description: "DMZ B subnet ID"
Value: !Ref subnetDmzB
Export:
Name: !Sub ${AWS::StackName}-DmzSubnetBId
DmzSubnetCId:
Description: "DMZ C subnet ID"
Value: !Ref subnetDmzC
Export:
Name: !Sub ${AWS::StackName}-DmzSubnetCId
SubnetAppAId:
Description: "App A subnet ID"
Value: !Ref subnetAppA
Export:
Name: !Sub ${AWS::StackName}-SubnetAppAId
SubnetAppBId:
Description: "App B subnet ID"
Value: !Ref subnetAppB
Export:
Name: !Sub ${AWS::StackName}-SubnetAppBId
SubnetAppCId:
Description: "App C subnet ID"
Value: !Ref subnetAppC
Export:
Name: !Sub ${AWS::StackName}-SubnetAppCId
SubnetDbAId:
Description: "DB A subnet ID"
Value: !Ref subnetDbA
Export:
Name: !Sub ${AWS::StackName}-SubnetDbAId
SubnetDbBId:
Description: "DB B subnet ID"
Value: !Ref subnetDbB
Export:
Name: !Sub ${AWS::StackName}-SubnetDbBId
SubnetDbCId:
Description: "DB C subnet ID"
Value: !Ref subnetDbC
Export:
Name: !Sub ${AWS::StackName}-SubnetDbCId
Validate the template:
aws cloudformation validate-template --template-body file://vpc-example-1.yaml
If there are no errors, create the stack.
Remember to pass the parameters for the
x.y
shown above.
aws cloudformation create-stack --template-body file://vpc-example-1.yaml --parameters ParameterKey=VpcCidrPrefix,ParameterValue=10.0 --stack-name oj-test-stack
To list all the exports.
aws cloudformation list-exports --query 'Exports[].[Name,Value]' --output table
The output will be
------------------------------------------------------------
| ListExports |
+-----------------------------+----------------------------+
| oj-test-stack-DmzSubnetAId | subnet-0fb6a12ac99d3b1e6 |
| oj-test-stack-DmzSubnetBId | subnet-03882aa1d2eadbd78 |
| oj-test-stack-DmzSubnetCId | subnet-01e4c2fa5bbb158b4 |
| ... | ... |
| oj-test-stack-VpcCidr | 10.0.0.0/21 |
| oj-test-stack-VpcId | vpc-055a7ad17ccfa1fb7 |
+-----------------------------+----------------------------+
if you want information about the above VPC created as oj-test-stack
:
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=oj-test-stack"
to get only the VpcId:
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=oj-test-stack" --query 'Vpcs[0].VpcId' --output text
if you want to use the above VpcId , then assign that to a variable
VPC_ID=$(aws ec2...above command)
For example to list all the subnets and its cidr block:
aws ec2 describe-subnets --filters "Name=vpc-id,Values=${VPC_ID}" --query 'Subnets[].[SubnetId,CidrBlock,Tags[?Key==`Scope`]|[0].Value]' --output table
the output will be
---------------------------------------------------------
| DescribeSubnets |
+---------------------------+----------------+----------+
| subnet-01355rt561041ec99 | 10.0.6.16/28 | private |
| subnet-... | 10.0.3.0/24 | private |
| subnet-... | 10.0.6.32/28 | private |
| ... | 10.0.1.0/24 | public |
| subnet-... | 10.0.0.0/24 | public |
| subnet-... | 10.0.2.0/24 | public |
+---------------------------+----------------+----------+
More information such as AZ and number of availble IPs, you can get as follows:
aws ec2 describe-subnets --filters "Name=vpc-id,Values=${VPC_ID}" --query 'Subnets[].[Tags[?Key==`Name`]|[0].Value,SubnetId,CidrBlock,Tags[?Key==`Scope`]|[0].Value,AvailableIpAddressCount,AvailabilityZone]' --output table