ANS Exercise 1.5: IPv4 Subnet Fundamentals

January 17, 2020

ANS Exercise 1.5: IPv4 Subnet Fundamentals

In this exercise we will look at the basics of subnets in AWS Virtual Private Cloud. We will examine CIDRs, reserved IP addresses and subnet strategies.

This is exercise 1.5 for the AWS Advanced Networking Specialty training. For an explanation and overview of all exercises, see the overview post.

The exercises are built on the assumption that you’re already familiar with the AWS basics and have achieved at least one associate level AWS certification.

Create a VPC

Navigate to the VPC console. Contrary to previous exercises, we will not use the Launch VPC wizard this time. Instead, navigate to the “Your VPCs” section and click Create VPC.

1.5-create-vpc

In the next screen, hover over the (i) after the IPv4 CIDR block line.

1.5-vpc-size

You can choose any IP range (eg. 35.150.0.0/16 would work), but it’s advisable to stick to the RFC1918 ranges, meant for private networks. These are 10.0.0.0/8, 172.16.0.0/20 and 192.168.0.0/16.

The popup shows that the largest accepted range is /16 (good for 65531 addresses), and the smallest is /28 (with only 11 addresses).

The formula to calculate the maximum amount of available addresses in AWS is 2^(32 - subnet_size) - 5. For example 2^(32 - 16) - 5 = 65531. The reason we subtract five is that AWS reserves five addresses for internal use. We’ll get to the details of these reserved addresses later.

For now, choose 10.0.0.0/16 and click Create.

Splitting CIDRs

There is a lot of binary logic behind CIDR calculations. We will not go into all the details in this post, but two rules are important to remember:

  • In IPv4, a /32 CIDR equals exactly one address. For example: 8.8.8.8/32 is the exact address 8.8.8.8. Smaller suffixes (/31 and up) are ranges of IP addresses. For example: 8.8.8.0/24 is the range 8.8.8.0 - 8.8.8.255.
  • Any CIDR fits exactly two CIDRs that have a suffix that is one number bigger. For example: a /30 fits two /31 CIDRs.

If we look at the exact size of a CIDR (not available addresses), the formula is 2^(32 - CIDR_suffix): so a /32 CIDR has 2^(32-32) = 1 addresses, /31 has 2^(32-31) = 2 addresses, and a /30 has 2^(32-30) = 4 addresses.

Take all of this information for granted and accept that any CIDR fits two CIDRs with a suffix that is one higher.

One big subnet

If we would add one single subnet in our VPC, we could make it as large as /16 (the size of the VPC). Let’s try this now. Navigate to the Subnets section of the VPC console and click the “Create subnet” button.

1.5-create-subnet

Fill in the following details, which will let the subnet fill the entire VPC space:

1.5-create-one-big-subnet

Then select the subnet, and look at the Description tab at the bottom. As you can see, it says there are 65531 available addresses.

1.5-65531-available-addresses

Reserved addresses

Amazon reserves five addresses in every subnet:

  • The first address in a subnet is the network address
  • The second is the router’s address
  • The third is the DNS server’s address (also see the exercise DNS Fundamentals)
  • The fourth is reserved for future use
  • The last address in a subnet is the broadcast address

In our example subnet of 10.0.0.0/16, these would translate to:

  • 10.0.0.0 network address
  • 10.0.0.1 router address
  • 10.0.0.2 DNS server address
  • 10.0.0.3 reserved
  • 10.0.255.255 broadcast address

Every address between 10.0.0.3 and 10.0.255.255 can be used for resources, which corresponds with the 65531 mentioned earlier.

In an example subnet with a CIDR of 10.0.0.0/28, the reserved addresses would be:

  • 10.0.0.0 network address
  • 10.0.0.1 router address
  • 10.0.0.2 DNS server address
  • 10.0.0.3 reserved
  • 10.0.0.15 broadcast address

The eleven addresses 10.0.0.4 - 10.0.0.14 are free to use.

Multiple subnets

In our previous example we deployed one single subnet. Because it uses the entire VPC CIDR, we can’t deploy any additional subnets.

Subnets are always limited to a single availability zone. Because best practice would be to deploy resources in at least three availability zones, a single big subnet is not the best idea.

Let’s delete the big subnet and replace it with three smaller ones. Configure the small ones like this:

1.5-subnet-per-az

For AZ 1b, use CIDR block 10.0.64.0/18, and for AZ 1c use 10.0.128.0/18.

Remember from earlier in this post that a /16 fits two /17’s? By extension, a /16 fits four /18’s. Because we need at least three subnets, the largest subnet size we can use is a /18.

Each of these subnets has 2^(32 - 18) = 16384 available addresses, which is quite acceptable. However, the CIDR 10.0.192.0/18 is now unused, leading to 16384 unusable addresses. To visualize this:

Blank Diagram

Because every subnet has 5 reserved addresses, the total amount of available addresses is now 3 * (2^(32 - 18) - 5) = 49137

Private and public subnets

However, it’s unlikely we will be using only public subnets. Good cloud native design requires us to have public resources (like load balancers) and private resources (like databases and web servers).

To achieve this, we could equally split the environment in six subnets (three public and three private).

Blank Diagram - Copy of Page 1

The amount of available addresses would now be 6 * (2^(32 - 19) - 5) = 49122, which is comparable to what we previously had.

In this design, all public resources (think NAT gateways, load balancers, bastion hosts and so on) would share the same public subnets. The same goes for the private resources like databases, webservers, EMR workers and so on).

Because an environment is likely to have more private resources than public resources, this could lead to over-utilized private subnets and under-utilized public subnets.

That’s why there is a third alternative.

A CIDR per service

You could also split your VPC in a CIDRs per service. For example, split your /16 into 32 ‘virtual’ CIDRs of /21 each. This gives you blocks with 2048 addresses per service, which is enough for most use cases. For example:

Service ID CIDR Function
0 x.x.0.0/21 Web servers
1 x.x.8.0/21 RDS
2 x.x.16.0/21 EFS
3 x.x.24.0/21 NAT
4 x.x.32.0/21 ElasticSearch
5 x.x.40.0/21 Redis
6 x.x.48.0/21 Load balancers

In the table above, we haven’t yet taken availability zones into account. Because we need three zones, we will need to split every /21 into four /23 CIDRs. The result would be something like this:

Service ID Function AZ CIDR
0 Web servers 1a x.x.0.0/23
0 Web servers 1b x.x.2.0/23
0 Web servers 1c x.x.4.0/23
1 RDS 1a x.x.8.0/23
1 RDS 1b x.x.10.0/23
1 RDS 1c x.x.12.0/23
2 EFS 1a x.x.16.0/23
2 EFS 1b x.x.18.0/23
2 EFS 1c x.x.20.0/23

Every subnet would have (2^(32 - 23) - 5) = 507 addresses available. This would be enough for most use cases, but for some workloads this might not be the best design and you would need to fiddle with the CIDR sizing.

Conclusion

In this exercise we’ve created VPC with a number of subnets in different sizes. We’ve seen that choosing a larger size subnets impacts your flexibility. Smaller subnets provide a lot more flexibility, but naturally limit the amount of resources you can deploy in a subnet.

Because Amazon reserves five IP addresses per subnet, more subnets also lead to more overhead.

Luc van Donkersgoed

Luc van Donkersgoed