AWS CloudFormation - VPC Nested Stack
In this article I would like provide you with a simple CloudFormation nested script (YAML) that creates the following.
- A VPC - 2 Public Subnets in 2 Availability Zones - 2 Private Subnets in 2 Availability Zones - An Internet Gateway - Route table for Public Subnets, Routes and Route table association - Route table for Private Subnets, Routes and Route table association - NAT Gateways in 2 Public Subnets (one in each AZ) - Output of VPC and all the Subnet
1. Master Script (master.yaml)
The first one is a Master script which will invoke the nested child script when uploaded in S3.
Description: >
This is a master stack template deploys vpc child stack which will in turn deploy the following.
- VPC
- 2 Public Subnets in 2 Availability Zones
- 2 Private Subnets in 2 Availability Zones
- Internet Gateway
- Route table for Public Subnets, Routes and Route table association
- Route table for Private Subnets, Routes and Route table association
- NAT Gateways in 2 Public Subnets (one in each AZ)
- Output of VPC and all the Subnet
Last Modified: 06-Feb-2021
Author: Praveen Kumar PS <praveen_ps@yahoo.com>
Resources:
VPC:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://mycfstack.s3.amazonaws.com/vpc.yaml
Parameters:
EnvironmentName: !Ref AWS::StackName
VpcCIDR: 10.0.0.0/16
PublicSubnet1CIDR: 10.0.1.0/24
PublicSubnet2CIDR: 10.0.2.0/24
PrivateSubnet1CIDR: 10.0.3.0/24
PrivateSubnet2CIDR: 10.0.4.0/24
#======================================================================
# END OF MASTER SCRIPT.
#======================================================================
1. Child Script (vpc.yaml)
The second one is a child script which will execute the nested vpc yaml script to create vpc and other resources mentioned above.
Description: >
This template deploys the following
- VPC
- 2 Public Subnets in 2 Availability Zones
- 2 Private Subnets in 2 Availability Zones
- Internet Gateway
- Route table for Public Subnets, Routes and Route table association
- Route table for Private Subnets, Routes and Route table association
- NAT Gateways in 2 Public Subnets (one in each AZ)
- Output of VPC and all the Subnets
#======================================================================
# THE FOLLOWING SECTION IS PARAMETER SECTION WHERE YOU DEFINE THE NECESSARY PARAMETERS REQUIRED
# TO DEPLOY THE VPC AND ITS COMPONENTS.
#======================================================================
Parameters:
EnvironmentName:
Description: MyTestEnvironment
Type: String
Default: MyTestEnvironment
VpcCIDR:
Description: IP range (CIDR notation) for this VPC
Type: String
Default: 10.0.0.0/16
PublicSubnet1CIDR:
Description: IP range (CIDR notation) for the public subnet in the first Availability Zone
Type: String
Default: 10.0.1.0/24
PublicSubnet2CIDR:
Description: IP range (CIDR notation) for the public subnet in the second Availability Zone
Type: String
Default: 10.0.2.0/24
PrivateSubnet1CIDR:
Description: IP range (CIDR notation) for the private subnet in the first Availability Zone
Type: String
Default: 10.0.3.0/24
PrivateSubnet2CIDR:
Description: IP range (CIDR notation) for the private subnet in the second Availability Zone
Type: String
Default: 10.0.4.0/24
AvailabilityZone1:
Description: Details of first Availability Zone
Type: String
Default: us-east-1a
AvailabilityZone2:
Description: Details of second Availability Zone
Type: String
Default: us-east-1b
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref EnvironmentName
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Ref AvailabilityZone1
CidrBlock: !Ref PublicSubnet1CIDR
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet1 (AZ1)
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Ref AvailabilityZone2
CidrBlock: !Ref PublicSubnet2CIDR
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Subnet2 (AZ2)
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Ref AvailabilityZone1
CidrBlock: !Ref PrivateSubnet1CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet1 (AZ1)
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Ref AvailabilityZone2
CidrBlock: !Ref PrivateSubnet2CIDR
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Subnet2 (AZ2)
NatGateway1EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
NatGateway2EIP:
Type: AWS::EC2::EIP
DependsOn: InternetGatewayAttachment
Properties:
Domain: vpc
NatGateway1:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway1EIP.AllocationId
SubnetId: !Ref PublicSubnet1
NatGateway2:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGateway2EIP.AllocationId
SubnetId: !Ref PublicSubnet2
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Public Routes
PublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet2
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Routes (AZ1)
PrivateRoute1:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway1
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable1
SubnetId: !Ref PrivateSubnet1
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName} Private Routes (AZ2)
PrivateRoute2:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable2
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway2
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable2
SubnetId: !Ref PrivateSubnet2
Outputs:
VPC:
Description: A reference to the created VPC
Value: !Ref VPC
PublicSubnets:
Description: A list of the public subnets
Value: !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]]
PrivateSubnets:
Description: A list of the private subnets
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
PublicSubnet1:
Description: A reference to the public subnet in the 1st Availability Zone
Value: !Ref PublicSubnet1
PublicSubnet2:
Description: A reference to the public subnet in the 2nd Availability Zone
Value: !Ref PublicSubnet2
PrivateSubnet1:
Description: A reference to the private subnet in the 1st Availability Zone
Value: !Ref PrivateSubnet1
PrivateSubnet2:
Description: A reference to the private subnet in the 2nd Availability Zone
Value: !Ref PrivateSubnet2
3. How to upload?
- Copy the master file as master.yaml and child script as vpc.yml
- Create a bucket in S3 and name it as you wish (the script has the name as mycfstack)
- Upload both the scripts in the created bucket
- Go to Cloud Formation
- Create New Stack

- Provide location of Master script in S3 as shown below

- Click Next and provide a stack name. Click next and then click create stack button.

- Your stack will be executed in less than 5 mins.

Please navigate to VPC section of your AWS console to confirm if VPC and other components mentioned created properly.
Note: Creating a NAT Gateway is Chargeable as it will be associated with Elastic IP. So if you do not need NAT Gateway, you can comments that portion of code in VPC yaml file.
I hope the above script will be useful to AWS beginners who are working or practicing cloud formation. Please provide your valuable comments on this article if this is of any help. Kindly share this with your known groups if you like it. Thanks.