In this article we will clarify how to use AWS Cloud Formation (CF) templates in forming your Virtual Private Cloud (VPC) and its network, including private and public subnets, internet gateways, routes, security groups, network access control lists, etc.
There are a lot of good articles written explaining about best practices and how to build your VPC. But if you want to use AWS Cloud Formation templates for your VPC then pay attention. We will explain why you would want to do this and what building blocks you may need in order to form your VPC.
Let’s start with clarifying what is AWS VPC. According to Wikipedia:
“Amazon Virtual Private Cloud is a commercial cloud computing service that provides users a virtual private cloud, by provisioning a logically isolated section of Amazon Web Services Cloud. Enterprise customers are able to access the Amazon Elastic Compute Cloud over an IPsec based virtual private network.”
And here is what AWS tells us what AWS Cloud Formation is:
“AWS CloudFormation is a service that helps you model and set up your Amazon Web Services resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want (like Amazon EC2 instances or Amazon RDS DB instances), and AWS CloudFormation takes care of provisioning and configuring those resources for you. You don’t need to individually create and configure AWS resources and figure out what’s dependent on what; AWS CloudFormation handles all of that.”
Simply put, a VPC is a software-defined network optimized for performance to transmit network packets into, out of, and across AWS regions. It plays a crucial role in your computing infrastructure placement as well as security. It defines the logical boundaries for your infrastructure within the cloud and protects your assets, if done right.
You can build your VPC in two ways. The simplest way is to use AWS Management Console to create and manage VPCs. However, this approach cannot be automated and usually cannot be incrementally improved since it is hard to measure (read = visualize) and keep track of all the elements used - most likely.
The other way to build your VPCs is to use AWS Cloud Formation. Cloud Formation is a product within the AWS infrastructure that allows you to describe your infrastructure using templates and then apply those templates to automatically provision your cloud resources. Also, using CF visualization tools, you can see your infrastructure at a glance, analyze it and improve it over time, known as the “Infrastructure As Code” (IaC) paradigm.
Here is an example of a simple AWS CF template for forming a simple VPC:
AWSTemplateFormatVersion = "2010-09-09"
Description = >
This is a simple VPC CloudFormation template
Parameters:
VPCCIDR:
Description = CIDR notation for your VPC
Type = String
Default = 172.30.0.0/16
Subnet1CIDR:
Description = CIDR notation for the public subnet
Type = String
Default = 172.30.0.0/24
Subnet3CIDR:
Description = CIDR notation for the private subnet
Type = String
Default = 172.30.1.0/24
Resources:
VPC:
Type = AWS::EC2::VPC
Properties:
EnableDnsSupport = 'true'
EnableDnsHostnames = 'true'
CidrBlock = !Ref VPCCIDR
Tags:
- Key = Application
Value:
Ref = AWS::StackId
- Key = Name
Value = My VPC
InternetGateway:
Type = AWS::EC2::InternetGateway
Properties:
Tags:
- Key = Application
Value:
Ref = AWS::StackName
- Key = Network
Value = Public
Tags =
- Key = Name
Value = VPC IG
PublicSubnet1 =
Type = AWS::EC2::Subnet
Properties:
VpcId = !Ref VPC
AvailabilityZone = !Select [ 0, !GetAZs '' ]
CidrBlock = !Ref Subnet1CIDR
MapPublicIpOnLaunch = true
Tags =
- Key = Name
Value = VPC Public Subnet (AZ1)
PrivateSubnet1:
Type = 'AWS::EC2::Subnet'
Properties:
VpcId = !Ref VPC
AvailabilityZone = !Select [ 0, !GetAZs '' ]
CidrBlock = !Ref Subnet3CIDR
MapPublicIpOnLaunch = false
Tags:
- Key = Name
Value = VPC Private Subnet (AZ2)
InternetGateway:
Type = AWS::EC2::InternetGateway
Properties:
Tags:
- Key = Name
Value = !Join [_, [!Ref 'AWS::StackName']]
GatewayToInternet:
Type = AWS::EC2::VPCGatewayAttachment
Properties:
VpcId = !Ref VPC
InternetGatewayId = !Ref InternetGateway
PublicRouteTable:
Type = AWS::EC2::RouteTable
Properties:
VpcId = !Ref VPC
Tags:
- Key = Name
Value = !Join [_, [!Ref 'AWS::StackName']]
PrivateRouteTable:
Type = AWS::EC2::RouteTable
Properties:
VpcId = !Ref VPC
PrivateSubnet1RouteTableAssociation:
Type = AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId = !Ref PrivateSubnet1
RouteTableId = !Ref PrivateRouteTable
PublicRoute:
Type = AWS::EC2::Route
DependsOn = GatewayToInternet
Properties:
RouteTableId = !Ref PublicRouteTable
DestinationCidrBlock = 0.0.0.0/0
GatewayId = !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type = AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId = !Ref PublicSubnet1
RouteTableId = !Ref PublicRouteTable
Outputs:
VPCID:
Description = VPC ID
Value = !Ref VPC
PublicSubnet1:
Description = Public Subnet 1
Value = !Ref PublicSubnet1
PrivateSubnet1:
Description = Private Subnet 1
Value = !Ref PrivateSubnet1
What this template will provision, once you apply it, is a VPC with public and private subnets and their attachments. Public subnet will be exposed to the Internet, so any resource placed in this subnet will be accessible from the Internet. You may place your web server into it, for example.
Private subnet, on the other hand, does not have public exposure, and so it is more secure and well-suited for database and/or application servers. What is interesting here is the other attachments that you absolutely need in order to achieve such network topology.
Here is a diagram of our VPC:
Even though it may not be clear first, we have few implicit elements here = VPC’s building blocks that allow traffic flow across a wire into and out of our network = GatewayToInternet (GTI), Route, InternetGateway (IG) and a RouteTable (RT). It’s very important to understand that Route and RouteTable are different things = from the physical network, you may have your Router but you forgot to configure connectivity through it. As well as InternetGateway and GatewayToInternet - you may have a device but it may not be connected to the Internet.
When you provision your VPCs you need to be very explicit in your template for the Cloud Formation service what you are actually trying to accomplish, otherwise you may spent hours or days trying to understand why something does not work as you would expect.
Let’s consider a public subnet for a second. To make a subnet to be public, you need to have a Router that must have attachments such as InternetGateway, GatewayToInternet AND a rule in your public RouteTable to allow traffic flow through the Router. Hopefully that makes sense. Here is a visualization of what we just said:
As for the private subnet, things are a little simpler here, you just need to have a private RouteTable that does not have attached Router.
Unless restricted by the Security Groups and/or Network Access Control Lists, it is important to keep in mind that within your VPC all your resources CAN communicate IF, AND ONLY IF, you have route tables that allow traffic flow into and out of your subnets.
Using AWS Cloud Formation templates to provision your infrastructure is a powerful way to quickly and reliably build your cloud infrastructure. You can even combine AWS Cloud Formation templates with other AWS services such as Elastic Beanstalk to achieve higher efficiency.
Here at Konstankino we utilize AWS Cloud Formation as it helps us to spend less time on provisioning services and reduces the chance of making a mistake. Because we are more efficient, we can concentrate on our value-added work, such as writing the code for our customers. Feel free to reach out should you need help with AWS Cloud.