How to use Cloudformation to create a VPC on AWS

Using Cloudformation, we can create and manage AWS resources very easily.  Cloudformation can be used to manage all AWS resources using a text file. Cloudformation allows us to create and model our infrastructure and applications without having to perform actions manually. Cloudformation helps us to manage our complete infrastructure in a text file, or template. Cloudformation template is a formatted text file in JSON or YAML language that describes our AWS infrastructure. 

In this article, we will see a Cloudformation to create a VPC with 2 Public and 2 Private Subnets.

Pre-requisites

  1. AWS Account (Create if you don’t have one). 
  2. Basic understanding of Cloudformation Templates.

What we will do?

  1. Login to AWS.
  2. Create a template.
  3. Create a Cloudformation Stack 

Login to AWS

  1. Click here to go to AWS Login Page.

When we hit the above link, we will see a web page as follows where we are required to login using our login details.

Login to AWS

Once we login into AWS successfully, we will see the main console with all the services listed as follows.

AWS Management Console

Create a template

Before we proceed with creating a stack, we should have a template that will be used to create a VPC. Copy the following code and save in on a local machine.

---
AWSTemplateFormatVersion: 2010-09-09
Description: >
  This Templates creates a VPC with 3 public and 3 private subnets.
Parameters:
  VpcCIDR:
    TypeString
    DescriptionVPC CIDR (Do Not Change if no customization is required). 
    Default10.10.0.0/16
  PrivateAZ1SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 1st Availability Zone (Do Not Change if no customization is required).
    Default10.10.80.0/21
  PrivateAZ2SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 2nd Availability Zone (Do Not Change if no customization is required).
    Default10.10.88.0/21
  PrivateAZ3SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 3rd Availability Zone (Do Not Change if no customization is required).
    Default10.10.96.0/21
  PublicAZ1SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 1st Availability Zone (Do Not Change if no customization is required).
    Default10.10.0.0/21
  PublicAZ2SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 2nd Availability Zone (Do Not Change if no customization is required).
    Default10.10.8.0/21
  PublicAZ3SubnetCIDR:
    TypeString
    DescriptionSubnet CIDR for 3rd Availability Zone (Do Not Change if no customization is required). 
    Default10.10.16.0/21
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          defaultVPC
        Parameters:
          - VpcCIDR
      - Label:
          defaultAvailabilty Zone 1
        Parameters:
          - PublicAZ1SubnetCIDR
          - PrivateAZ1SubnetCIDR
      - Label:
          defaultAvailabilty Zone 1
        Parameters:
          - PublicAZ2SubnetCIDR
          - PrivateAZ2SubnetCIDR
      - Label:
          defaultAvailabilty Zone 1
        Parameters:
          - PublicAZ3SubnetCIDR
          - PrivateAZ3SubnetCIDR
Resources:
  Vpc:
    TypeAWS::EC2::VPC
    Properties:
      CidrBlock!Ref VpcCIDR
      Tags:
        - KeyName
          Value!Sub ${AWS::StackName}
  InternetGateway:
    TypeAWS::EC2::InternetGateway
    Properties:
      Tags:
        - KeyName
          Value!Sub ${AWS::StackName}
  VPCGatewayAttachment:
    TypeAWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId!Ref InternetGateway
      VpcId!Ref Vpc
  # Public Subnets - Route Table
  PublicRouteTable:
    TypeAWS::EC2::RouteTable
    Properties:
      VpcId!Ref Vpc
      Tags:
        - KeyName
          Value!Sub ${AWS::StackName}-public
        - KeyType
          Valuepublic
  PublicSubnetsRoute:
    TypeAWS::EC2::Route
    Properties:
      RouteTableId!Ref PublicRouteTable
      DestinationCidrBlock0.0.0.0/0
      GatewayId!Ref InternetGateway
    DependsOnVPCGatewayAttachment
  # Public Subnets
  PublicAZ1Subnet:
    TypeAWS::EC2::Subnet
    Properties:
      VpcId!Ref Vpc
      CidrBlock!Ref PublicAZ1SubnetCIDR
      AvailabilityZone!Select [0!GetAZs ""]
      MapPublicIpOnLaunchtrue
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-public-${AZ}
            - { AZ!Select [0!GetAZs ""] }
        - KeyType
          Valuepublic
  PublicAZ1SubnetRouteTableAssociation:
    TypeAWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId!Ref PublicAZ1Subnet
      RouteTableId!Ref PublicRouteTable
  PublicAZ2Subnet:
    TypeAWS::EC2::Subnet
    Properties:
      VpcId!Ref Vpc
      CidrBlock!Ref PublicAZ2SubnetCIDR
      AvailabilityZone!Select [1!GetAZs ""]
      MapPublicIpOnLaunchtrue
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-public-${AZ}
            - { AZ!Select [1!GetAZs ""] }
        - KeyType
          Valuepublic
  PublicAZ2SubnetRouteTableAssociation:
    TypeAWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId!Ref PublicAZ2Subnet
      RouteTableId!Ref PublicRouteTable
  PublicAZ3Subnet:
    TypeAWS::EC2::Subnet
    Properties:
      VpcId!Ref Vpc
      CidrBlock!Ref PublicAZ3SubnetCIDR
      AvailabilityZone!Select [2!GetAZs ""]
      MapPublicIpOnLaunchtrue
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-public-${AZ}
            - { AZ!Select [2!GetAZs ""] }
        - KeyType
          Valuepublic
  PublicAZ3SubnetRouteTableAssociation:
    TypeAWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId!Ref PublicAZ3Subnet
      RouteTableId!Ref PublicRouteTable
  # Private Subnets - NAT Gateways
  AZ1NatGatewayEIP:
    TypeAWS::EC2::EIP
    Properties:
      Domainvpc
    DependsOnVPCGatewayAttachment
  AZ1NatGateway:
    TypeAWS::EC2::NatGateway
    Properties:
      AllocationId!GetAtt AZ1NatGatewayEIP.AllocationId
      SubnetId!Ref PublicAZ1Subnet
  AZ2NatGatewayEIP:
    TypeAWS::EC2::EIP
    Properties:
      Domainvpc
    DependsOnVPCGatewayAttachment
  AZ2NatGateway:
    TypeAWS::EC2::NatGateway
    Properties:
      AllocationId!GetAtt AZ2NatGatewayEIP.AllocationId
      SubnetId!Ref PublicAZ2Subnet
  AZ3NatGatewayEIP:
    TypeAWS::EC2::EIP
    Properties:
      Domainvpc
    DependsOnVPCGatewayAttachment
  AZ3NatGateway:
    TypeAWS::EC2::NatGateway
    Properties:
      AllocationId!GetAtt AZ3NatGatewayEIP.AllocationId
      SubnetId!Ref PublicAZ3Subnet
  # Private Subnets
  PrivateAZ1Subnet:
    TypeAWS::EC2::Subnet
    Properties:
      VpcId!Ref Vpc
      CidrBlock!Ref PrivateAZ1SubnetCIDR
      AvailabilityZone!Select [0!GetAZs ""]
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-private-${AZ}
            - { AZ!Select [0!GetAZs ""] }
        - KeyType
          Valueprivate
  PrivateAZ1RouteTable:
    TypeAWS::EC2::RouteTable
    Properties:
      VpcId!Ref Vpc
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-private-${AZ}
            - { AZ!Select [0!GetAZs ""] }
        - KeyType
          Valueprivate
  PrivateAZ1Route:
    TypeAWS::EC2::Route
    Properties:
      RouteTableId!Ref PrivateAZ1RouteTable
      DestinationCidrBlock0.0.0.0/0
      NatGatewayId!Ref AZ1NatGateway
  PrivateAZ1RouteTableAssociation:
    TypeAWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId!Ref PrivateAZ1Subnet
      RouteTableId!Ref PrivateAZ1RouteTable
  PrivateAZ2Subnet:
    TypeAWS::EC2::Subnet
    Properties:
      VpcId!Ref Vpc
      CidrBlock!Ref PrivateAZ2SubnetCIDR
      AvailabilityZone!Select [1!GetAZs ""]
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-private-${AZ}
            - { AZ!Select [1!GetAZs ""] }
        - KeyType
          Valueprivate
  PrivateAZ2RouteTable:
    TypeAWS::EC2::RouteTable
    Properties:
      VpcId!Ref Vpc
      Tags:
        - KeyName
          Value!Sub
            - ${AWS::StackName}-private-${AZ}
            - { AZ!Select [1