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.


379 views0 comments