Week 4

VPC - An analogy about shared resources

Public subnets and Internet Gateway

Private subnets and NAT

Endpoints and Security Groups

Putting it all together

Load balancing - one front door, many clerks

Auto Scaling

Architecture and Tradeoffs

Practice

Assignment

Cloud Track

Under construction

<aside> 🚧

This page is currently under construction. Please check back later.

</aside>

<aside> 🧱

Step 3 of 3 — building the week's architecture

Availability Zone A is done: a public subnet with hyf-web and your hyf-bastion jump box, a private subnet with hyf-app. This section adds the last tier — a private subnet in a second Availability Zone holding the database hyf-db — and then locks the whole thing down.

Two new tools do that work: VPC endpoints, so the most protected subnet needs no NAT Gateway at all, and Security Groups, so each machine accepts traffic only from the one tier that is supposed to talk to it.

After this page, the diagram from the Week 4 overview is complete.

</aside>


So far every machine you built can talk to every other machine, because every security group allows the whole VPC CIDR and every subnet shares the same routes. That is a network, but it is not yet an architecture.

The difference is intent. In a real system you can say, out loud, who is allowed to talk to whom:

The internet may talk to the web server, and only on port 80. The web server may talk to the app server, and only on port 3000. The app server may talk to the database, and only on port 5432. You may log in to the bastion, and only the bastion may log in to anything else. Nothing else is allowed, in any direction.

This section is about making AWS enforce those five sentences. We do it in three moves: put the database somewhere structurally harder to reach (a private subnet in another AZ), give it the one outside service it genuinely needs without giving it the internet (endpoints), and then write the rules themselves (security groups).

Step 1 The third tier: a private subnet in another Availability Zone

Why a second Availability Zone?

An Availability Zone is one or more physically separate data centres — separate power, separate cooling, separate network. Putting your database in a different AZ from your application means a fire, flood or power failure in AZ A does not take your data with it.

Two things are worth understanding before you click anything:

<aside> 💭

Back to the analogy: Availability Zones are districts of the city, and your VPC is a set of buildings you own across those districts. The private post office you were given (the local route) delivers between all of your buildings, whichever district they are in. What it will never do on its own is deliver to an address outside your buildings.

</aside>

Create the subnet

  1. In the VPC console, go to Subnets → Create subnet.
  2. Select your existing VPC (hyf-week4-vpc).
  3. Name it hyf-week4-private-subnet-b.
  4. Pick a different Availability Zone from the previous two — eu-central-1b.
  5. Set a non-overlapping IPv4 CIDR block: 10.0.3.0/24.
  6. Click Create subnet.

Screenshot 2026-08-29 at 11.45.49.png

Give it its own route table — with no way out

This is the part that makes this subnet more isolated than the previous one. hyf-week4-private-subnet-a has a 0.0.0.0/0 route to the NAT Gateway, so hyf-app can reach the whole internet outbound. The database does not need that, so we will not give it that.

  1. In Route tables, create a new route table named hyf-week4-private-rt-b, in your VPC.
  2. Do not add any route. Leave it with only the local route AWS creates for you.
  3. Open Subnet associations → Edit subnet associations → tick hyf-week4-private-subnet-b.

Screenshot 2026-08-29 at 11.47.01.png

<aside> 💭

Read that route table out loud: "traffic to my own VPC goes to my own VPC; everything else has nowhere to go." A machine in this subnet can be reached by any other machine in the VPC, and can reply — but it cannot start a conversation with anything on the internet, and nothing on the internet can address it. This is the strongest isolation you can get while still being on the network.

</aside>

Launch the database (EC2) in it

  1. Launch an instance named hyf-db, selecting hyf-week4-private-subnet-b in Network settings.
  2. Auto-assign public IP: disabled.
  3. For the security group, create one named hyf-db-sg with a single temporary rule: SSH (22) from 10.0.0.0/16, so you can reach it through the bastion. We tighten it in Step 3.
  4. Under Advanced details → IAM instance profile, attach a role that may use S3. If you don't have one: IAM console → Roles → Create role → AWS service → EC2, attach AmazonS3FullAccess, name it hyf-db-role. (A real system would scope that policy to a single bucket; here we want permissions to stop being an interesting variable.)
  5. Once it is running, note its private IP.

<aside> 💭

An IAM role on an instance is how a machine gets AWS credentials without anyone ever putting a password on it: the instance asks a link-local address for temporary keys, which rotate by themselves. That answers "who is allowed to call this service". Everything else on this page answers "how does the request physically get there". Two different questions — and mixing them up is the most common reason a failing aws command takes an hour to diagnose.

</aside>

You also need somewhere to put a backup. If you don't have one already, create an S3 bucket in eu-central-1 (S3 console → Create bucket, defaults are fine, the name has to be globally unique).

Screenshot 2026-08-29 at 14.58.56.png

Connect to it — through the bastion

hyf-bastion sits in the public subnet in AZ A. hyf-db sits in a private subnet in AZ B whose route table has no way out at all. And yet this works, first time:

ssh -i key.pem -J ec2-user@<bastion-public-ip> ec2-user@<db-private-ip>

Take a second to see why. The packet from the bastion to 10.0.3.x matches the local route, and local spans every subnet in every AZ of the VPC. Administering this machine needs no internet, no gateway and no public IP, because the bastion is inside the VPC — it is on the same private network as everything else you have built.

That is the argument for a bastion in one sentence: it still works for a subnet that has no route to the outside world at all.

Now try to do something useful — and watch it fail

A database nobody can administer is useless. So is one that cannot take a backup. From your shell on hyf-db:

echo "pretend this is a database dump" > /tmp/backup.sql
aws s3 cp /tmp/backup.sql s3://<your-bucket-name>/ --region eu-central-1

It hangs for a while, then fails with a connection timeout. So does curl https://example.com. Nothing addressed outside 10.0.0.0/16 has anywhere to go — exactly what you designed one step ago, and now exactly what is in your way.

<aside> 💡

If instead you get Unable to locate credentials straight away, that is a different failure: the IAM role is not attached to the instance. Fix that first — we want to watch a network failure, not a permissions one. Slow failure = network. Instant failure = credentials or permissions.

</aside>

You have three options:

  1. Add a 0.0.0.0/0 → NAT route to hyf-week4-private-rt-b — which throws away the isolation you just built, and pays a NAT Gateway by the hour to carry your backups out of the VPC and straight back into AWS.
  2. Never let this machine talk to any AWS service — no backups, no logs, no secrets. Not realistic.
  3. Give it a private door to S3 specifically, and nothing else. That is a VPC endpoint.

Step 2 VPC endpoints: reaching AWS services without leaving the VPC

A VPC endpoint is a private connection from your VPC straight to a supported AWS service, without the traffic ever touching the public internet — and without needing a NAT Gateway, an Internet Gateway, or a public IP anywhere in the path.

There are two kinds:

Gateway endpoint Interface endpoint
Works for S3 and DynamoDB only Most AWS services, including Systems Manager
How it appears A target in a route table A network interface (ENI) with a private IP inside your subnet
Cost Free Small hourly fee + data processing
Secured by Route table + endpoint policy Security group on the endpoint itself

They achieve the same thing by completely different means, and being precise about which is which saves a lot of confused debugging later:

We use the gateway endpoint here: S3 is what a database actually needs, and it costs nothing.

Create the S3 gateway endpoint

  1. In the VPC console, go to Endpoints → Create endpoint.
  2. Name it hyf-week4-s3-endpoint.
  3. Type: AWS services. Search for s3 and select com.amazonaws.eu-central-1.s3 — the one whose Type column says Gateway. (There is an Interface entry with an almost identical name; that column is the only thing telling them apart.)
  4. VPC: hyf-week4-vpc.
  5. Route tables: tick hyf-week4-private-rt-b. That is the entire configuration — a gateway endpoint has no subnet and no security group. It belongs to the route tables you tick here.
  6. Policy: leave it on Full access for now.
  7. Create endpoint.

Now go back to Route tables → hyf-week4-private-rt-b → Routes. There is a line there you did not write: destination pl-xxxxxxxx (a prefix list), target vpce-xxxxxxxx. Your "no way out" route table now has exactly one way out, and it leads to S3 and nowhere else.

Try the backup again

Back in your shell on hyf-db (through the bastion), run the same commands: