CA2 · AWS PRACTICAL

AWS Exam Step-by-Step Guide

14 Sections · Ubuntu OS · VPC · CloudWatch · AMI · GitHub App Deploy

00VPC Setup 01Launch Template 02Load Balancer 03Target Group 04Auto Scaling 05Scaling Policy 06EBS Volume 07EFS 08S3 Bucket 09Storage Mount 10Target Check 11AMI 12CloudWatch 13GitHub App + DB
00

VPC Setup

Web-VPC

VPC is your private network inside AWS. All your resources (EC2, ALB, ASG) live inside it.

1

Search VPC in the top bar → Click Your VPCsCreate VPC

2

Select VPC and more (this auto-creates subnets, route tables, and internet gateway)

3

Name tag: Web-VPC

4

IPv4 CIDR: 10.0.0.0/16

5

Number of AZs: 2, Public subnets: 2, Private subnets: 2

6

NAT Gateways: None (to avoid cost) → Click Create VPC

Use this VPC when creating your ALB, ASG, and EC2 instances. Always pick the public subnets for internet-facing resources.

Key VPC Concepts to Know:

SUBNET
Sub-division of VPC (public/private)
INTERNET GATEWAY
Allows internet traffic in/out
ROUTE TABLE
Rules for where traffic goes
SECURITY GROUP
Firewall for each resource
📷 SCREENSHOT NEEDED (if asked)
  • VPC name (Web-VPC) with CIDR visible
  • Subnets list showing public subnets
01

Launch Template

Web-LT
1

Go to EC2 → Left sidebar → Launch Templates → Click Create launch template

2

Enter name: Web-LT

3

Under Application and OS Images → Search and select Amazon Linux 2023 AMI

4

Instance type: t2.micro

5

Under Network settings → Create security group → Name it Web-SG

6

In Inbound rules → Add two rules: SSH (port 22) and HTTP (port 80), both from 0.0.0.0/0

7

Scroll down to Advanced details → Paste this in User Data:

#!/bin/bash
dnf install -y nginx
systemctl enable nginx
systemctl start nginx
echo "Hello from $(hostname)" > /usr/share/nginx/html/index.html
8

Click Create launch template

📷 SCREENSHOT NEEDED
  • Launch template name (Web-LT)
  • Instance type (t2.micro)
  • Security group (Web-SG with SSH + HTTP)
  • User Data section
02

Application Load Balancer

Web-ALB
1

Go to EC2 → Left sidebar → Load BalancersCreate load balancer

2

Choose Application Load Balancer

3

Name: Web-ALB

4

Scheme: Internet-facing (not internal)

5

Under Listeners → Protocol: HTTP, Port: 80

6

Select at least 2 Availability Zones (select your VPC and subnets)

7

For security group → select Web-SG

8

For now, you can skip target group (we create it next) → click Create load balancer

📷 SCREENSHOT NEEDED
  • Load Balancer name (Web-ALB)
  • Scheme (Internet-facing)
  • Listener (HTTP port 80)
03

Target Group

Web-TG
1

Go to EC2 → Left sidebar → Target GroupsCreate target group

2

Target type: Instances

3

Name: Web-TG

4

Protocol: HTTP, Port: 80

5

Under Health checks → Health check path: /

6

Click Next → Skip adding instances for now → Click Create target group

After creating Web-TG, go back to your Load Balancer (Web-ALB) → Listeners tab → Edit listener → Forward to Web-TG
📷 SCREENSHOT NEEDED
  • Target group name (Web-TG)
  • Health check path (/)
04

Auto Scaling Group

Web-ASG
1

Go to EC2 → Left sidebar → Auto Scaling GroupsCreate Auto Scaling group

2

Name: Web-ASG

3

Launch template: Select Web-LT → Click Next

4

Choose your VPC and select at least 2 subnets → Click Next

5

Attach to load balancer → Select Attach to an existing load balancer → Choose Web-TG

6

Set capacity:

MINIMUM
2
DESIRED
2
MAXIMUM
4
7

Click Next through remaining steps → Create Auto Scaling group

📷 SCREENSHOT NEEDED
  • ASG name (Web-ASG)
  • Capacity (Min:2, Desired:2, Max:4)
  • Target group attachment (Web-TG)
05

Scaling Policy

Web-CPU-Policy
1

Go to Auto Scaling Groups → Click on Web-ASG

2

Click the Automatic scaling tab → Create dynamic scaling policy

3

Policy type: Target tracking scaling

4

Scaling policy name: Web-CPU-Policy

5

Metric type: Average CPU utilization

6

Target value: 50 (scale when CPU goes above 50%)

7

Click Create

📷 SCREENSHOT NEEDED
  • Policy name (Web-CPU-Policy)
  • CPU metric selected
06

EBS Volume

Web-EBS
1

Go to EC2 → Left sidebar → VolumesCreate volume

2

Size: 8 GiB (default is fine)

3

Availability Zone: Must match the AZ of your EC2 instance

4

Click Create volume → After created, add a Name tag: Web-EBS

5

Select the volume → ActionsAttach volume → Choose one of your running instances → Click Attach

The AZ of the EBS volume MUST match the AZ of the instance. If it says "no instances found", the AZ is wrong.
📷 SCREENSHOT NEEDED
  • Volume name (Web-EBS)
  • Attached instance ID visible
07

EFS (Elastic File System)

Web-EFS
1

Go to EFS service (search in top bar) → Create file system

2

Name: Web-EFS

3

VPC: Select your VPC → Click Create

4

Click on Web-EFS → Go to Network tab → You will see mount targets for each AZ

Mount targets allow your EC2 instances to connect to EFS. Make sure the security group allows NFS (port 2049) traffic.
📷 SCREENSHOT NEEDED
  • File system name (Web-EFS)
  • Mount targets shown (with AZ info)
08

S3 Bucket

web-static-storage-<yourname>
1

Go to S3 service → Create bucket

2

Bucket name: web-static-storage-sijomon (use your actual name, all lowercase)

3

Region: Select your region

4

Leave everything else default → Create bucket

S3 bucket names must be globally unique and lowercase only. No spaces or uppercase allowed.
📷 SCREENSHOT NEEDED
  • Bucket name visible (web-static-storage-yourname)
09

Storage Mount (SSH into EC2)

df -h

You need to SSH into your EC2 instance and run these commands.

Step A — Mount EBS to /data

# Check what the EBS device name is
lsblk
# You will see something like /dev/xvdf or /dev/nvme1n1

# Format the disk (only first time!)
sudo mkfs.ext4 /dev/xvdf

# Create the mount point
sudo mkdir /data

# Mount it
sudo mount /dev/xvdf /data

# Verify
df -h

Step B — Mount EFS to /shared

# Install EFS utilities
sudo dnf install -y amazon-efs-utils

# Create the mount point
sudo mkdir /shared

# Go to EFS console → Click Web-EFS → Copy the mount command
# It will look like this (replace fs-xxxxxxxx with your EFS ID):
sudo mount -t efs -o tls fs-xxxxxxxx:/ /shared

# Verify both /data and /shared are visible
df -h
After running df -h, look for /data and /shared in the output. Take the screenshot of that terminal output.
📷 SCREENSHOT NEEDED
  • /data visible in df -h output
  • /shared visible in df -h output
10

Target Group Health Check

Web-TG
1

Go to EC2Target Groups → Click on Web-TG

2

Click the Targets tab at the bottom

3

You should see your 2 instances (from ASG) with status Healthy

4

Copy the DNS name of Web-ALB → Paste in browser → You should see:
Hello from ip-xxx-xxx-xxx-xxx

If instances show "unhealthy", wait 2-3 minutes. Nginx needs time to start. Also make sure port 80 is open in Web-SG.
📷 SCREENSHOT NEEDED
  • Both instances showing "Healthy" status in Web-TG
11

Create AMI (Machine Image)

Web-AMI

An AMI is a snapshot/copy of your EC2 instance. You can use it to launch identical instances quickly — very useful for scaling.

1

Go to EC2Instances → Select one of your running instances

2

Click ActionsImage and templatesCreate image

3

Image name: Web-AMI

4

Leave everything else default → Click Create image

5

Go to AMIs (left sidebar under Images) → Wait for status to change to Available

AMI creation takes 2–5 minutes. You can use this AMI later in your Launch Template instead of the default Amazon Linux AMI — it will already have nginx and your app installed.

Why AMI is useful in exam:

# Without AMI → every new instance runs User Data script from scratch
# With AMI  → every new instance already has nginx + your app ready
# Faster boot, consistent environment ✓
📷 SCREENSHOT NEEDED
  • AMI name (Web-AMI) with status "Available"
  • Source instance ID visible
12

CloudWatch — Monitoring

Web-CPU-Alarm

CloudWatch monitors your AWS resources. You can set alarms when CPU, memory, or other metrics go too high.

Part A — View EC2 Metrics

1

Go to CloudWatch → Left sidebar → MetricsAll metrics

2

Click EC2Per-Instance Metrics → Search CPUUtilization → Select your instance

3

You will see a graph of CPU usage over time

Part B — Create an Alarm

4

Go to CloudWatchAlarmsCreate alarm

5

Click Select metric → EC2 → Per-Instance Metrics → Select CPUUtilization for your instance → Click Select metric

6

Threshold: Greater than 70 (alarm when CPU > 70%)

7

Skip notification for now → Alarm name: Web-CPU-Alarm → Click Create alarm

Part C — View ASG Metrics (Dashboard)

8

Go to CloudWatchDashboardsCreate dashboard → Name it Web-Dashboard

9

Add a widget → Line chart → Select EC2 CPUUtilization → Save

📷 SCREENSHOT NEEDED
  • Alarm name (Web-CPU-Alarm) with threshold visible
  • Metric graph showing CPUUtilization
13

Deploy App from GitHub + Database

GitHub + MySQL

This is the "simple website with database backend" part. The plan: store your website code on GitHub → clone it on EC2 → connect it to a MySQL database.

Step A — Create a simple app on GitHub (do this before exam)

Create a repo on GitHub with these files:

# File: index.html
<!DOCTYPE html>
<html>
<head><title>My AWS App</title></head>
<body>
  <h1>Hello from AWS!</h1>
  <p>Deployed via GitHub on EC2</p>
</body>
</html>

Step B — SSH into EC2 and clone the repo

# SSH into your EC2 instance first
ssh -i your-key.pem ec2-user@<your-ec2-ip>

# Install git (if not already installed)
sudo dnf install -y git

# Clone your GitHub repo
git clone https://github.com/yourusername/your-repo-name.git

# Copy files to nginx web root
sudo cp -r your-repo-name/* /usr/share/nginx/html/

# Restart nginx
sudo systemctl restart nginx

Step C — Install MySQL (Database Backend)

# Install MySQL server
sudo dnf install -y mysql-server

# Start and enable MySQL
sudo systemctl enable --now mysqld

# Secure the installation (set root password)
sudo mysql_secure_installation

# Login to MySQL
sudo mysql -u root -p

# Inside MySQL — create a database and table
CREATE DATABASE webappdb;
USE webappdb;
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('Sijomon', 'test@email.com');
SELECT * FROM users;
EXIT;

Step D — Use User Data to auto-deploy from GitHub (in Launch Template)

Update your Web-LT User Data to this so every new instance auto-clones your repo:

#!/bin/bash
dnf install -y nginx git mysql-server
systemctl enable nginx mysqld
systemctl start nginx mysqld

# Clone your GitHub repo directly
git clone https://github.com/yourusername/your-repo-name.git /tmp/myapp
cp -r /tmp/myapp/* /usr/share/nginx/html/

# Show hostname so we know which instance served the request
echo "Served by: $(hostname)" >> /usr/share/nginx/html/index.html
Make your GitHub repo PUBLIC so EC2 can clone it without a login. This is the easiest way during exam time.
📷 SCREENSHOT NEEDED
  • git clone command running successfully in terminal
  • MySQL SELECT * FROM users showing data
  • Website visible in browser via EC2 IP or ALB DNS