Compute & Database
Launch EC2 instances, configure Auto Scaling Groups, set up RDS PostgreSQL, and load-balance with ALB.
What You'll Build
With your networking in place, it's time to deploy compute and database resources. You'll create an RDS PostgreSQL database, an Application Load Balancer, and an Auto Scaling Group โ all through the AWS Console.
Module 2 โ Resource Checklist
0/8 (0%)- โIAM Role
sandbox-ec2-role - โKey Pair
sandbox-key - โDB Subnet Group
sandbox-db-subnet-group - โRDS Instance
sandbox-db - โTarget Group
sandbox-tg - โApplication Load Balancer
sandbox-alb - โLaunch Template
sandbox-lt - โAuto Scaling Group
sandbox-asg
| Azure | AWS | Notes |
|---|---|---|
Virtual Machine | EC2 | Nearly identical concept |
VMSS | Auto Scaling Group | ASG + Launch Template โ VMSS |
Azure DB for PostgreSQL | RDS PostgreSQL | Very similar. AWS has DB Subnet Groups |
App Gateway | ALB | ALB is simpler; App Gateway has built-in WAF |
Managed Identity | IAM Instance Profile | Attach IAM Role to EC2 for permissions |
Step 1: Create an IAM Role for EC2
EC2 instances need an IAM Role to interact with AWS services (SSM for terminal access, CloudWatch for logs, S3 for deployments). This is like Azure Managed Identity.
Console: IAM โ Roles โ Create role
Step 1 โ Trusted entity:
| Setting | Value |
|---|---|
| Trusted entity type | AWS service |
| Use case | EC2 |
Click Next.
Step 2 โ Permissions: Search and select these policies:
| Policy Name | Purpose |
|---|---|
AmazonSSMManagedInstanceCore | SSM Session Manager (SSH alternative) |
CloudWatchAgentServerPolicy | Send logs/metrics to CloudWatch |
AmazonS3ReadOnlyAccess | Pull deployment artifacts from S3 |
Click Next.
Step 3 โ Name:
| Setting | Value |
|---|---|
| Role name | sandbox-ec2-role |
Click Create role.
Step 2: Create a Key Pair
For emergency SSH access. You'll primarily use SSM Session Manager (no SSH needed), but a key pair is a good backup.
Console: EC2 โ Key Pairs โ Create key pair
| Setting | Value |
|---|---|
| Name | sandbox-key |
| Key pair type | RSA |
| Private key file format | .pem (Mac/Linux) |
Click Create key pair โ the .pem file downloads. Save it!
# Make it usable (run in your terminal)
chmod 400 ~/Downloads/sandbox-key.pemStep 3: RDS PostgreSQL
RDS (Relational Database Service) is a managed database. AWS handles backups, patching, and failover โ you just connect and query.
- DB Subnet Group: Tells RDS which subnets to use (must span 2+ AZs)
- Multi-AZ: Automatic failover to standby in another AZ (production feature)
- Instance Class:
db.t3.microis free-tier eligible
Azure Database for PostgreSQL uses VNet integration or Private Endpoints. AWS RDS uses Security Groups + DB Subnet Groups โ functionally equivalent.
Console: RDS โ Subnet groups โ Create DB subnet group
| Setting | Value |
|---|---|
| Name | sandbox-db-subnet-group |
| Description | Private subnets for AWS Sandbox RDS |
| VPC | sandbox-vpc |
Add subnets:
| AZ | Subnet |
|---|---|
us-east-1a | sandbox-private-1a (10.0.10.0/24) |
us-east-1b | sandbox-private-1b (10.0.11.0/24) |
Click Create.
Console: RDS โ Databases โ Create database
| Setting | Value |
|---|---|
| Creation method | Standard create |
| Engine type | PostgreSQL |
| Engine version | PostgreSQL 15 (latest 15.x) |
| Templates | Free tier |
| DB instance identifier | sandbox-db |
| Master username | dbadmin |
| Master password | Choose a strong password (note it!) |
| DB instance class | db.t3.micro |
| Storage type | gp2 |
| Allocated storage | 20 GB |
| Storage autoscaling | โ Uncheck |
| VPC | sandbox-vpc |
| DB subnet group | sandbox-db-subnet-group |
| Public access | No |
| Security group | sandbox-rds-sg (remove default!) |
| Initial database name | sandbox |
| Enhanced Monitoring | โ Uncheck |
Click Create database. Wait 5-10 minutes for Available.
Copy the endpoint! Click sandbox-db โ under Connectivity & security โ copy the Endpoint(e.g., sandbox-db.xxxxx.us-east-1.rds.amazonaws.com). You'll need it for the Launch Template.
Step 4: Application Load Balancer
The ALB distributes incoming HTTP/HTTPS traffic across your EC2 instances. It sits in public subnets and forwards to a Target Group.
๐ ALB
The load balancer itself. Lives in public subnets, has its own DNS name.
๐ฏ Target Group
A collection of targets (EC2 instances) with health check configuration.
๐ Listener
Listens on a port (80/443) and routes traffic to the target group.
Console: EC2 โ Target Groups โ Create target group
| Setting | Value |
|---|---|
| Target type | Instances |
| Target group name | sandbox-tg |
| Protocol : Port | HTTP : 3000 |
| VPC | sandbox-vpc |
| Health check path | /health |
| Healthy threshold | 2 |
| Unhealthy threshold | 3 |
| Timeout | 5 seconds |
| Interval | 30 seconds |
Click Next. Skip registering targets (ASG will handle this). Click Create target group.
Console: EC2 โ Load Balancers โ Create โ Application Load Balancer
| Setting | Value |
|---|---|
| Name | sandbox-alb |
| Scheme | Internet-facing |
| IP address type | IPv4 |
| VPC | sandbox-vpc |
| Mappings | โ
us-east-1a โ sandbox-public-1a |
โ
us-east-1b โ sandbox-public-1b | |
| Security groups | sandbox-alb-sg (remove default!) |
| Listener: Protocol | HTTP |
| Listener: Port | 80 |
| Listener: Default action | Forward to โ sandbox-tg |
Click Create load balancer. Wait ~2-3 minutes until Active.
Copy the DNS name! Select sandbox-alb โ copy the DNS name (e.g., sandbox-alb-123456.us-east-1.elb.amazonaws.com). This is your public URL.
Step 5: EC2 Auto Scaling Group
Instead of launching individual EC2 instances, you'll use a Launch Template (blueprint) + Auto Scaling Group (scales up/down).
VMSS comparison: Azure VMSS bundles image and scaling config in one resource. AWS separates them: Launch Template (image config) + ASG (scaling).
Console: EC2 โ Launch Templates โ Create launch template
| Setting | Value |
|---|---|
| Launch template name | sandbox-lt |
| Template version description | Initial v1 |
| AMI | Amazon Linux 2023 |
| Instance type | t3.micro |
| Key pair | sandbox-key |
| Security groups | sandbox-ec2-sg |
| IAM instance profile (Advanced) | sandbox-ec2-role |
User data (in Advanced details, paste this script):
#!/bin/bash
set -e
# Install Node.js 18
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs git
# Install CodeDeploy agent (for later CI/CD module)
yum install -y ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
chmod +x ./install
./install auto
# Create the application directory
mkdir -p /home/ec2-user/sandbox-app/app
cd /home/ec2-user/sandbox-app/app
# Initialize app and install dependencies
npm init -y
npm install express pg dotenv
# Create the Express server inline
cat > server.js << 'EOF'
const express = require('express');
const { Pool } = require('pg');
const os = require('os');
require('dotenv').config();
const app = express();
app.use(express.json());
// Set up Postgres connection pool
const pool = new Pool({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
});
// The crucial /health endpoint for the ALB
app.get('/health', (req, res) => {
res.status(200).send('OK');
});
// Provide instance hostname to prove ALB routing
app.get('/api/info', (req, res) => {
res.json({ hostname: os.hostname(), message: 'Hello from EC2 Auto Scaling!' });
});
// Dummy task API
app.get('/api/tasks', (req, res) => {
res.json([{ id: 1, title: 'Sample task', description: 'DB not connected in demo' }]);
});
app.post('/api/tasks', (req, res) => {
res.status(201).json({ status: 'created' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
EOF
# Create environment file
cat > .env << 'ENVEOF'
PORT=3000
NODE_ENV=production
DB_HOST=REPLACE_WITH_YOUR_RDS_ENDPOINT
DB_PORT=5432
DB_NAME=sandbox
DB_USER=dbadmin
DB_PASSWORD=REPLACE_WITH_YOUR_RDS_PASSWORD
ENVEOF
# Start the app with PM2
npm install -g pm2
pm2 start server.js --name sandbox
pm2 startup
pm2 saveBefore creating: Replace DB_HOST with your RDS endpoint from Step 3, and DB_PASSWORD with your RDS password!
Click Create launch template.
Console: EC2 โ Auto Scaling Groups โ Create
Step 1 โ Launch template:
| Setting | Value |
|---|---|
| ASG name | sandbox-asg |
| Launch template | sandbox-lt |
Step 2 โ Network:
| Setting | Value |
|---|---|
| VPC | sandbox-vpc |
| Subnets | sandbox-private-1a, sandbox-private-1b |
Step 3 โ Load balancing:
| Setting | Value |
|---|---|
| Load balancing | Attach to existing load balancer |
| Target group | sandbox-tg |
| Health check type | โ ELB |
| Health check grace period | 300 seconds |
Step 4 โ Group size:
| Setting | Value |
|---|---|
| Desired capacity | 2 |
| Minimum capacity | 1 |
| Maximum capacity | 4 |
| Scaling policy | Target tracking |
| Metric | Average CPU utilization |
| Target value | 70 |
Click through Next โ Create Auto Scaling group.
Wait 3-5 minutes. Then check:
- EC2 โ Instances โ 2 new instances should appear
- EC2 โ Target Groups โ
sandbox-tgโ Targets โ both should become healthy
๐งช Test the Full Deployment
Once your target group shows healthy targets, open your ALB DNS in a browser or use curl:
# Replace with YOUR ALB DNS name
ALB_DNS="sandbox-alb-123456.us-east-1.elb.amazonaws.com"
# Health check
curl http://$ALB_DNS/health
# List tasks
curl http://$ALB_DNS/api/tasks
# Create a task
curl -X POST http://$ALB_DNS/api/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Learn AWS VPC", "description": "Understand CIDR blocks"}'
# Hit /api/info multiple times โ notice the hostname changes!
# That's the ALB distributing traffic across ASG instances.
curl http://$ALB_DNS/api/info
curl http://$ALB_DNS/api/infoLoad balancing proof: Call /api/info repeatedly. Each response shows a different hostname โ proving the ALB is routing across your ASG instances.
Key Takeaways
- RDS handles database management โ you focus on queries, AWS handles backups/patching
- ALB + Target Group is the standard pattern for HTTP load balancing
- Launch Template + ASG = reproducible, auto-healing, auto-scaling compute
- User Data scripts run only on first boot โ update the Launch Template to change config
- The
/healthendpoint is critical โ it's how the ALB knows which instances are alive - Always use IAM Roles for EC2 (never embed access keys in code)