By the end you'll know
- What a VPC (virtual private cloud) is, and why the default one isn't the bakery's network
- How to read an address range like 10.8.0.0/16, and why a subnet of 256 addresses gives you 251
- What a route table does, and the one route that makes a subnet public
- What an internet gateway and a NAT (network address translation) gateway each do, and what each costs
- Why tags matter, and why AWS makes you delete things in a particular order
Before you start
- You need: the
juniper-ryeprofile from Lesson 4, signed in. - The script:
vpc-lab.shfrom the practice folder'slesson-08. Everything it creates is namedjr-lesson8-*and taggedlesson=8, and itsdeletestep removes it. - Where you run things: your own machine, labelled (Your machine).
- Every output below is from a real run on November 9, 2026.
One part of this lesson bills by the hour
The network itself is free. The VPC, subnets, route tables and internet gateway cost nothing, whether you keep them or not. The NAT gateway costs $0.045 an hour, $32.85 a month, busy or idle, and a partial hour bills as a full one. The lab's nat step creates one and deletes it in the same step, about 5 cents in all. Never leave one running in a practice account.
The short version
- A VPC is the bakery's own network inside AWS, with an address range it chooses.
- Subnets divide it, and each subnet lives in one Availability Zone.
- A route table decides where a subnet's traffic goes. A subnet is public only because its route table sends
0.0.0.0/0to an internet gateway. - An internet gateway is free and works both ways. A NAT gateway lets private servers reach out, lets nothing in, and costs $32.85 a month.
- The default VPC makes every subnet public. That's convenient for a test and wrong for anything real.
- Tag everything, and delete in reverse order of building.
What this lesson costs
| Part | Cost |
|---|---|
| Dry runs, prices, looking at the default VPC | $0 |
| The VPC, 4 subnets, 2 route tables, an internet gateway | $0, even if left in place |
| One NAT gateway for about 3 minutes, and its public IPv4 address | $0.045 + $0.005, each billed as a full hour |
| This lesson | About 5 cents, from credits |
| If the NAT gateway were left running | $32.85 a month, plus $3.65 for its address |
The bakery's building
Lightsail, in Lesson 7, hid the network: you got a server with an address, and AWS handled the rest. Everything from here on, EC2 servers, databases, load balancers, lives in a network you design. Think of it as the bakery's own building on AWS's land:
| In AWS | In the building | What it does |
|---|---|---|
| VPC | The building | Your private network, with its own address range, in one Region |
| Subnet | A room | A slice of the address range, in one Availability Zone |
| Route table | The signs in a room's hallway | Where traffic from that subnet goes next |
| Internet gateway | The front door | The way in and out to the internet. Free. |
| NAT gateway | A staff exit that only opens outward | Lets private servers reach out; nobody outside can come in through it |
Is it allowed, and what does it cost?
(Your machine)
cd ~/Apps/aws-practice/lesson-08
chmod +x vpc-lab.sh
./vpc-lab.sh fence
== Can this account build networks in us-east-2? (dry runs: nothing is created)
create a VPC allowed
create an internet gateway allowed
reserve a public IPv4 address allowed
create a NAT gateway allowed (the made-up IDs in the test were rejected, as expected)
== What a NAT gateway costs in us-east-2 (from the AWS Price List)
for existing: $0.045 an hour, $32.85 for a 730-hour month, busy or idle
for data through: $0.045 per GB
plus its public IPv4 address: $0.005 an hour (Lesson 1)
== Everything else this lab builds (VPC, subnets, route tables, internet gateway): $0
Each check uses --dry-run: AWS checks permission and answers DryRunOperation without creating anything. The NAT gateway test used made-up IDs, so AWS got past the permission check and then rejected the IDs, which means it's allowed. The price is the same as Lesson 1 found in Virginia, and it's charged twice: for every hour it exists, and again for every GB that passes through it.
The network AWS already made
In the console: VPC > Your VPCs: the default VPC says Yes in the Default VPC column. Subnets lists its subnets.
(Your machine)
./vpc-lab.sh default
== The default VPC in us-east-2
address range: 172.31.0.0/16
== Its subnets
zone addresses free gives servers a public IPv4?
us-east-2a 172.31.0.0/20 4091 yes
us-east-2b 172.31.16.0/20 4091 yes
us-east-2c 172.31.32.0/20 4091 yes
== Its route table
172.31.0.0/16 -> local (stays inside the VPC)
0.0.0.0/0 -> internet gateway
Lesson 5 found this default VPC: AWS makes one in each Region so a new server has somewhere to go. Look at what it does: one subnet per zone, every one gives servers a public IPv4 address, and its route table sends everything to the internet gateway. Launch a database here without thinking, and it's on the internet.
The default VPC puts everything on the internet
Every subnet in the default VPC is public. It's fine for a quick test, but real workloads get their own VPC with private subnets, so a database or an internal service can't be reached from outside at all.
What the slash means
An IPv4 address is four numbers, like 10.8.1.20. Each number is 8 bits, so 0 to 255, and the whole address is 32 bits. A range like 10.8.0.0/16 is CIDR (Classless Inter-Domain Routing) notation: the number after the slash says how many bits, counting from the left, are locked. Every address in the range starts with those bits. The bits left over are free to change, and every combination of them is one address in the range.
When the slash is 8, 16 or 24, that's whole numbers locked:
| Written | Locked | Free to change | Covers | Addresses |
|---|---|---|---|---|
10.0.0.0/8 | The first number, 10 | The last three | 10.0.0.0 to 10.255.255.255 | 16,777,216 |
10.8.0.0/16, the bakery's VPC | The first two, 10.8 | The last two | 10.8.0.0 to 10.8.255.255 | 65,536 |
10.8.1.0/24, one bakery subnet | The first three, 10.8.1 | The last one | 10.8.1.0 to 10.8.1.255 | 256 |
Two rules fall out of that:
- A smaller number after the slash means a bigger range. Each step of 1 doubles it or halves it: /23 is 512 addresses, /24 is 256, /25 is 128. A range holds 2 to the power of (32 minus the slash) addresses.
- A subnet must fit inside its VPC.
10.8.0.0/24and10.8.1.0/24both start with10.8, so both sit inside10.8.0.0/16, and they don't overlap each other.
The default VPC's /20 subnets split a number in the middle. 20 bits is the first two numbers (16 bits) plus 4 bits of the third. Those 4 free bits give the third number 16 values, and the last number's 256 values make 4,096 addresses. That's why the run showed the default subnets starting at 172.31.0.0, 172.31.16.0 and 172.31.32.0: each one takes the next block of 16 in the third number.
Usable is 5 fewer. The run showed 4,091 free in each /20, not 4,096, because AWS keeps 5 addresses in every subnet: the network address, the VPC router, DNS (Domain Name System), one held for future use, and the last one. A /24 gives you 251.
The bakery's range comes from 10.0.0.0/8, one of the private ranges set aside by RFC (Request for Comments) 1918 and never used on the public internet. A VPC's range must be between /16 (65,536 addresses) and /28 (16), so a whole /8 is too big; the bakery takes a /16 slice of it. For more practice, the Networking track's Subnets and CIDR lesson works through it slowly, with a range you can drag.
Build the bakery's network
In the console: VPC > Create VPC. VPC only makes just the VPC, and you add subnets, an internet gateway and route tables from their own pages. VPC and more builds all of it at once, with a preview of the map.
(Your machine)
./vpc-lab.sh build
== Building jr-lesson8-vpc in us-east-2
VPC 10.8.0.0/16 (65,536 addresses)
internet gateway, attached
subnet jr-lesson8-public-a 10.8.0.0/24 us-east-2a
subnet jr-lesson8-public-b 10.8.1.0/24 us-east-2b
subnet jr-lesson8-private-a 10.8.10.0/24 us-east-2a
subnet jr-lesson8-private-b 10.8.11.0/24 us-east-2b
route tables jr-lesson8-public-routes (with a route to the internet gateway)
jr-lesson8-private-routes (no way out)
== Built. Nothing here bills by the hour.
Two public and two private subnets, one of each in two zones, so that when Lesson 13 spreads the shop across zones, there's somewhere to put it. These are the calls that did it:
aws ec2 create-vpc --cidr-block 10.8.0.0/16 --tag-specifications "ResourceType=vpc,Tags=[...]"
aws ec2 create-internet-gateway ...
aws ec2 attach-internet-gateway --internet-gateway-id igw-... --vpc-id vpc-...
aws ec2 create-subnet --vpc-id vpc-... --cidr-block 10.8.0.0/24 --availability-zone us-east-2a ...
aws ec2 create-route-table --vpc-id vpc-... ...
aws ec2 create-route --route-table-id rtb-... --destination-cidr-block 0.0.0.0/0 --gateway-id igw-...
aws ec2 associate-route-table --route-table-id rtb-... --subnet-id subnet-...
| Call | What it does |
|---|---|
| create-vpc | Creates the building with its address range |
| create-internet-gateway, attach-internet-gateway | Makes the front door and fits it. A VPC has at most one. |
| create-subnet | Carves a /24 room out of the /16, in one zone. Done four times. |
| create-route-table | Makes an empty set of signs. Done twice: public and private. |
| create-route ... 0.0.0.0/0 --gateway-id | Adds one sign to the public table: everything else goes out the front door |
| associate-route-table | Hangs a table in a subnet. Each subnet uses exactly one. |
In the console, under VPC > Your VPCs, the bakery's network now sits next to the default one:
Public or private: one route
In the console: Your VPCs > pick the VPC > Resource map tab, or Route tables > pick one > Routes tab.
(Your machine)
./vpc-lab.sh show
== The subnets in jr-lesson8-vpc
subnet zone addresses free route table kind
jr-lesson8-private-a us-east-2a 10.8.10.0/24 251 jr-lesson8-private-routes private
jr-lesson8-private-b us-east-2b 10.8.11.0/24 251 jr-lesson8-private-routes private
jr-lesson8-public-a us-east-2a 10.8.0.0/24 251 jr-lesson8-public-routes public
jr-lesson8-public-b us-east-2b 10.8.1.0/24 251 jr-lesson8-public-routes public
== Routes in jr-lesson8-public-routes
10.8.0.0/16 -> local (stays inside the VPC)
0.0.0.0/0 -> internet gateway
== Routes in jr-lesson8-private-routes
10.8.0.0/16 -> local (stays inside the VPC)
The four subnets are identical except for one thing: which route table they use. Read the two tables:
10.8.0.0/16 -> localis in both. Every route table gets it automatically and you can't remove it: every room in the building can reach every other.0.0.0.0/0 -> internet gatewayis only in the public table.0.0.0.0/0means every address; when traffic matches nothing more specific, it goes out the front door. That one route is the whole difference between a public subnet and a private one.
A route table always uses the most specific match. Traffic for 10.8.1.20 matches both 10.8.0.0/16 and 0.0.0.0/0, so the /16 wins and it stays inside.
The console's Resource map tab draws the same thing:
Three route tables, not two. The middle one, shown only by its ID, is the main route table: AWS creates it with every VPC, and any subnet you don't attach to another table uses it. No subnet uses it here, because the lab attached every subnet to a table on purpose. Leaving subnets on the main table works, until someone adds a route to it and every unattached subnet changes at once.
Why that table has no name
The main route table is also the only thing on the map without a name, because the lab didn't create it, so it never got the lab's tags. A tag is a label, a key and a value, on almost anything in AWS. The lab tags everything it creates with three:
| Tag | What it does |
|---|---|
Name=jr-lesson8-... | What the console shows. Without it you get a column of IDs, like that third route table. |
lesson=8 | How the script's check step finds everything it made, in an account full of other things |
owner=juniper-rye | Who to ask. Once activated as a cost allocation tag in Billing, the bill can be split by it. |
Tag when you create, not later. Tagging an account full of untagged resources means working out what each one is first. Lesson 37 uses tags to split the bill.
A way out for private servers
A private server can't reach the internet at all, which also means it can't download security updates. The usual answer is a NAT gateway: it sits in a public subnet, and private subnets send their internet traffic to it. It forwards the traffic out under its own public address, and lets only the replies back in.
In the console: VPC > NAT gateways > Create NAT gateway, in a public subnet, with Allocate Elastic IP. Then Route tables > the private table > Edit routes.
(Your machine)
./vpc-lab.sh nat
== Creating a NAT gateway in jr-lesson8-public-a (billing starts now)
available after 109 seconds
== Routes in jr-lesson8-private-routes, with the NAT gateway
10.8.0.0/16 -> local (stays inside the VPC)
0.0.0.0/0 -> NAT gateway
== Deleting the NAT gateway and releasing its address
it existed for about 3 minutes
billed as 1 hour, because a partial hour counts as a whole one: about $0.05 in all
== Routes in jr-lesson8-private-routes, after
10.8.0.0/16 -> local (stays inside the VPC)
The step reserved a public IPv4 address, created the NAT gateway in jr-lesson8-public-a, waited 109 seconds for it, and gave the private table a 0.0.0.0/0 -> NAT gateway route. For those minutes, the private subnets could reach out and nothing could reach in. Then it removed the route, deleted the NAT gateway and released the address, all in one step, so it couldn't be forgotten.
Two rules for NAT gateways:
- It goes in a public subnet. Its own way out is the internet gateway; put it in a private subnet and it has nowhere to send traffic.
- One per zone, for real workloads. A NAT gateway lives in one zone. If that zone fails, private subnets in the other zone lose their way out too, so production designs use one in each zone, at $32.85 a month each.
The NAT gateway is the bill nobody expects
A NAT gateway costs $32.85 a month before a single byte passes through it, plus $0.045 for every GB that does. That's more than the bakery's server. In practice accounts, create it only when you need it and delete it straight after. Lesson 1's bill showed one NAT gateway costing more than twice the server.
The cheaper options are worth knowing. A NAT instance, an ordinary small server set up to forward traffic, does the same job for a few dollars a month, but you patch it, and it's a single point of failure. VPC endpoints let private servers reach some AWS services, such as S3, without going through the internet at all; the one for S3 is free. Lesson 13 comes back to both.
Take it down, in order
In the console: Your VPCs > pick the VPC > Actions > Delete VPC removes its subnets, route tables and internet gateway in one go, once any NAT gateways and servers are gone.
(Your machine)
./vpc-lab.sh delete
== Deleted jr-lesson8-vpc and everything in it
== Left over from this lab (tagged lesson=8)
VPCs: 0
subnets: 0
internet gateways: 0
== Things that bill by the hour, anywhere in us-east-2
NAT gateways: 0
public IPv4 (Elastic IP) addresses: 0
delete worked backwards through the building: NAT gateways and their addresses, then route tables, then subnets, then the internet gateway (detached, then deleted), then the VPC. AWS refuses to delete anything something else depends on: a VPC with a gateway attached, a subnet with a server in it, a route table still in use. Writing that order out by hand is fiddly, and getting it wrong leaves pieces behind. Lesson 29 builds this same network in Terraform, which works out the order itself.
The check looks twice: once for what the lab tagged, and once for anything in the Region that bills by the hour, tagged or not.
Where the rest of the network goes
Each subnet also has a network ACL (access control list), a firewall for the whole subnet. The default one allows everything, which is why this lab never noticed it. Lesson 9 covers network ACLs alongside security groups, the firewall around each server, and Lesson 10 launches servers into this network.
In real systems
- Teams plan address ranges across the whole company, so VPCs in different accounts and offices never overlap and can be connected later (Lesson 13). Two VPCs that both use 10.0.0.0/16 can't be joined.
- The usual layout is three tiers: public subnets for load balancers, private subnets for servers, and more private subnets for databases, in two or three zones.
- Many companies delete the default VPC in every Region, so nothing lands there by accident.
- NAT gateway data charges are a common surprise. Teams add VPC endpoints for S3 and other services so that traffic stops going through the NAT gateway.
- Nobody builds production networks by hand. It's Terraform or AWS CloudFormation, reviewed like code.
Spot the problem
Work out what's wrong before you read the explanation.
"We added a NAT gateway and the servers still can't get updates." A team puts its servers in private subnets. To let them install updates, someone creates a NAT gateway, places it in one of the private subnets, and adds 0.0.0.0/0 -> NAT gateway to the private route table. The NAT gateway shows as Available, and is billing $32.85 a month, but dnf update on every server still hangs. What's wrong? The NAT gateway is in a private subnet, so its own traffic has no way out. It forwards traffic to the private subnet's route table, which sends internet traffic... back to the NAT gateway. The fix: delete it and create it in a public subnet, whose route table points at the internet gateway, then point the private route at the new one. Then check: does the NAT gateway's subnet have a 0.0.0.0/0 -> internet gateway route, and does a private server's curl https://checkip.amazonaws.com return the NAT gateway's address?
Keep this
| Remember | Why |
|---|---|
| Public means a route to an internet gateway | 0.0.0.0/0 -> igw in its route table, and nothing else |
| Every subnet loses 5 addresses | A /24 gives you 251 |
| The default VPC is all public | Give real workloads their own VPC with private subnets |
| NAT gateways go in public subnets | They need the internet gateway themselves |
| A NAT gateway is $32.85 a month, idle | Delete it in practice accounts |
| Tag on create | Names in the console, finding things, splitting the bill |
| Delete in reverse order | AWS won't delete what something else depends on |
Where you are now
The bakery has its own network in Ohio: a /16 range, public and private subnets in two zones, an internet gateway, and route tables that decide which is which. A NAT gateway existed for three minutes and cost about 5 cents, and everything was deleted with nothing left billing. You can read an address range, find the route that makes a subnet public, and explain why the default VPC isn't good enough. Next, Lesson 9 puts firewalls on this network: security groups around each server and network ACLs around each subnet.
Check yourself
What makes a subnet public?
How many usable addresses does a /24 subnet have in AWS?
In the default VPC, what happens to a server launched without any network choices?
Where must a NAT gateway be created?
The NAT gateway existed for about 3 minutes. How much of its hourly charge was billed?
Why did the route table without a name appear on the Resource map?
Key terms
- VPC (virtual private cloud): your own private network in AWS, in one Region.
- Default VPC: the VPC AWS creates in each Region, with a public subnet in each zone.
- CIDR (Classless Inter-Domain Routing): an address range written as a starting address and a size, such as 10.8.0.0/16.
- Subnet: a slice of a VPC's range, in one Availability Zone.
- Route table: the rules a subnet follows to decide where its traffic goes.
- Main route table: the route table every VPC starts with, used by any subnet not attached to another.
- Internet gateway: a VPC's free, two-way connection to the internet.
- Public subnet: a subnet whose route table sends 0.0.0.0/0 to an internet gateway.
- Private subnet: a subnet with no route to an internet gateway.
- NAT (network address translation) gateway: lets private servers connect out without letting anything in; billed by the hour and by the GB.
- Elastic IP address: a public IPv4 address you reserve until you release it.
- VPC endpoint: a private way from a VPC to an AWS service, without the internet.
- Tag: a key and value label on an AWS resource.
Go deeper
- Networking track: Subnets and CIDR and Routing, NAT and private networks, the ideas under this lesson without AWS.
- AWS: How Amazon VPC works (opens in a new tab), and subnet sizing and the 5 reserved addresses (opens in a new tab).
- AWS: NAT gateways (opens in a new tab) and VPC pricing (opens in a new tab).
- Try: run
build, then in the console attachjr-lesson8-private-ato the public route table and runshow. What does the kind column say now? Rundeletewhen you're done.