You can define several VPCs. A VPC pretty much looks and feels like a traditional on-premises network, with subnets, route tables, and gateways, but it benefits from AWS's cloud infrastructure. Virtual Machines (EC2) in particular require a network, but other services such as AWS RDS or AWS Lambda are also now deployable into a VPC. A VPC can be used to communicate with your on-premises network, and VPCs can also communicate with each other via VPC Peering.
Typical AWS VPC design ^
A typical VPC design includes multiple subnets, routing tables, and usually an internet gateway to enable services in your VPC to communicate with the internet.
In this sample design, we see the concept of a public subnet and a private subnet. Technically, the subnets are the same; the public subnet is public because it has an Internet Gateway attached to it and a route table configured that routes 0.0.0.0/0 to the gateway. EC2 instances deployed into this subnet require public IPs attached to them to communicate to the internet. A private subnet has a route table configured that routes 0.0.0.0/0 to a NAT Gateway.
Creating an AWS VPC ^
To follow AWS best practices, we will create the following resources via PowerShell:
- AWS VPC
- Internet gateway
- NAT gateway + AWS elastic IP
- 2 subnets
- one private, one public
- 2 route tables
- one for each subnet
Note: Every AWS account and region already comes with a default VPC, which is perfectly suitable for getting started quickly. However, it doesn't follow best practices and most users actually delete the default VPCs.
I assume you have already authenticated your PowerShell to your AWS account. If not and you want to know how, just follow this article and then come back to continue with our scenario.
For this article, all resources will be created in the ap-southeast-2 (Sydney, Australia) region. Make sure you select one that fits your use case. We will also ignore the fact that you should build your infrastructure across multiple availability zones (as depicted in the screenshot). Now, we will require the VPC's ID for most of the following steps. We can either just remember it from the cmdlet's output or assign it to a variable. I will opt for the variable.
$vpc = New-EC2Vpc -CidrBlock 10.0.0.0/16 -Region ap-southeast-2
Next, we need to create an internet gateway and attach it to the VPC.
$igw = New-EC2InternetGateway
Add-EC2InternetGateway -VpcId $vpc.VpcId -InternetGatewayId $igw.InternetGatewayId
Our new VPC will now have internet connectivity. Right now, however, we don't have any subnets or route tables. We also need to create the NAT gateway in our private subnet. A NAT gateway must always be associated with an AWS elastic IP, which is a public IP address. We can do this all in one go. Creating the NAT gateway might take a couple of minutes, even though PowerShell will complete straightaway. In the AWS Console, you should wait with the next steps until the NAT gateway status changes to available (see the screenshot below).
$publicSubnet = New-EC2Subnet -VpcId $vpc.VpcId -CidrBlock 10.0.0.0/24
$privateSubnet = New-EC2Subnet -VpcId $vpc.VpcId -CidrBlock 10.0.2.0/24
$eip = New-EC2Address -Domain Vpc
$natgw = New-EC2NatGateway -SubnetId $privateSubnet.SubnetId -AllocationId $eip.AllocationId
These subnets now have enough room to host 251 IPv4 addresses each; for all intents and purposes, they are currently identical. We assigned one subnet to our $publicSubnet variable and the other one to the $privateSubnet variable. We also created an elastic IP address inside our VPC and a NAT gateway inside the private subnet that uses this elastic IP. Next, let's create some route tables and attach them to our subnets. First, we create a route table inside the VPC. Then we add a route and associate it with our subnet.
$publicRouteTable = New-EC2RouteTable -VpcId $vpc.VpcId
$privateRouteTable = New-EC2RouteTable -VpcId $vpc.VpcId
New-EC2Route -RouteTableId $publicRouteTable.RouteTableId -DestinationCidrBlock 0.0.0.0/0 -GatewayId $igw.InternetGatewayId
New-EC2Route -RouteTableId $privateRouteTable.RouteTableId -DestinationCidrBlock 0.0.0.0/0 -NatGatewayId $natgw.NatGateway.NatGatewayId
This has created two route tables, which we can also see inside our AWS Console now.
Finally, we associate these route tables with the correct subnets.
Register-EC2RouteTable -RouteTableId $publicRouteTable.RouteTableId -SubnetId $publicSubnet.SubnetId
Register-EC2RouteTable -RouteTableId $privateRouteTable.RouteTableId -SubnetId $privateSubnet.SubnetId
Once this is all executed without errors, you can check the AWS Console and see that you have two subnets in your VPC, each associated with the correct route table.
Your VPC is now ready to have workloads deployed into it.