Virtual private cloud
Amazon Virtual Private Cloud (Amazon VPC) enables customers to launch AWS resources into a virtual network dedicated to the customer's account. It is truly a customizable network that allows you to define your own IP address range, add and delete subnets, create routes, add VPN gateways, associate security policies, connect EC2 instances to your own datacenter, and much more. In the early days when VPC was not available, all EC2 instances in the AZ were on a single, flat network that was shared among all customers. How comfortable would the customer be with putting their information in the cloud? Not very, I'd imagine. Between the launch of EC2 in 2007 until the launch of VPC in 2009, VPC functions was one of the most requested features of AWS.
Since December 2013, all EC2 instances are VPC-only. If we use a launch wizard to create our EC2 instance, it will automatically be put into a default VPC with a virtual internet gateway for public access. In my opinion, all but the most basic use cases should use the default VPC. For most cases, we would need to define our non-default, customized VPC.
Let's create the following VPC using the AWS console in us-east-1:

If you recall, VPC is AWS region-bound, and the subnets are Availability Zone-based. Our first VPC will be based in us-east-1; the three subnets will be allocated to three different availability zones in 1a, 1b, and 1c.
Using the AWS console to create the VPC and subnets is pretty straightforward, and AWS provides a number of good tutorials online. I have listed the steps with the associated links on the VPC dashboard:

The first two steps are point and click processes that most network engineers can work through, even without prior experience. By default, the VPC only contains the local route, 10.0.0.0/16. Now, we will create an internet gateway and associate it with the VPC:

We can then create a custom route table with a default route pointing to the internet gateway. We will associate this route table with our subnet in us-east-1a, 10.0.0.0/24, thus allowing it to be public facing:

Let's use Boto3 Python SDK to see what we have created; I used the tag mastering_python_networking_demo as the tag for the VPC, which we can use as the filer:
$ cat Chapter9_1_query_vpc.py
#!/usr/bin/env python3
import json, boto3
region = 'us-east-1'
vpc_name = 'mastering_python_networking_demo'
ec2 = boto3.resource('ec2', region_name=region)
client = boto3.client('ec2')
filters = [{'Name':'tag:Name', 'Values':[vpc_name]}]
vpcs = list(ec2.vpcs.filter(Filters=filters))
for vpc in vpcs:
response = client.describe_vpcs(
VpcIds=[vpc.id,]
)
print(json.dumps(response, sort_keys=True, indent=4))
This script will allow us to programmatically query the region for the VPC we created:
$ python3 Chapter9_1_query_vpc.py
{
"ResponseMetadata": {
"HTTPHeaders": {
"content-type": "text/xml;charset=UTF-8",
...
},
"HTTPStatusCode": 200,
"RequestId": "48e19be5-01c1-469b-b6ff-9c45f2745483",
"RetryAttempts": 0
},
"Vpcs": [
{
"CidrBlock": "10.0.0.0/16",
"CidrBlockAssociationSet": [
{
"AssociationId": "...",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"DhcpOptionsId": "dopt-....",
"InstanceTenancy": "default",
"IsDefault": false,
"State": "available",
"Tags": [
{
"Key": "Name",
"Value": "mastering_python_networking_demo"
}
],
"VpcId": "vpc-...."
}
]
}
You may be wondering about how the subnets can reach one another within the VPC. In a physical network, the network needs to connect to a router to reach beyond its own local network. It is not so different in VPC, except it is an implicit router with a default routing table of the local network, which in our example is 10.0.0.0/16. This implicit router was created when we created our VPC.