Module 2

Compute & Database

Launch EC2 instances, configure Auto Scaling Groups, set up RDS PostgreSQL, and load-balance with ALB.

EC2ASGRDSALBLaunch Template

What You'll Learn

With your networking in place, it's time to deploy compute and database resources. You'll launch EC2 instances with Auto Scaling, set up RDS PostgreSQL, and load-balance with ALB.

AzureAWSNotes
Virtual MachineEC2Nearly identical concept
VMSSAuto Scaling GroupASG + Launch Template ≈ VMSS
Azure DB for PostgreSQLRDS PostgreSQLVery similar. AWS has DB Subnet Groups
App GatewayALBALB is simpler; App Gateway has built-in WAF
Managed IdentityIAM Instance ProfileAttach IAM Role to EC2 for permissions

Step 1: RDS PostgreSQL

RDS (Relational Database Service) is a managed database. AWS handles backups, patching, and failover — you just connect and query.

Key Concepts

  • DB Subnet Group: Tells RDS which subnets to use (must span 2+ AZs)
  • Multi-AZ: Automatic failover to a standby in another AZ (production feature)
  • Instance Class: db.t3.micro is free-tier eligible
☁️ Azure Parallel

Azure Database for PostgreSQL Flexible Server uses VNet integration or Private Endpoints for network isolation. AWS RDS uses Security Groups + DB Subnet Groups — functionally equivalent, different mechanism.

yaml03-rds.yaml
DBInstance:
  Type: AWS::RDS::DBInstance
  Properties:
    DBInstanceIdentifier: aws-sandbox-db
    Engine: postgres
    EngineVersion: '15.4'
    DBInstanceClass: db.t3.micro
    DBName: aws_sandbox
    MasterUsername: dbadmin
    MasterUserPassword: !Ref DBMasterPassword
    AllocatedStorage: 20
    StorageType: gp3
    DBSubnetGroupName: !Ref DBSubnetGroup
    VPCSecurityGroups:
      - !ImportValue aws-sandbox-RDSSecurityGroupId
    MultiAZ: false
    PubliclyAccessible: false

Step 2: 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.

Components

🔀 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.

Health Checks

The ALB pings /health on each instance every 30 seconds. If an instance fails 3 checks, it gets removed from rotation.

yaml04-alb.yaml
TargetGroup:
  Type: AWS::ElasticLoadBalancingV2::TargetGroup
  Properties:
    Port: 3000
    Protocol: HTTP
    VpcId: !ImportValue aws-sandbox-VpcId
    HealthCheckPath: /health
    HealthCheckIntervalSeconds: 30
    HealthyThresholdCount: 2
    UnhealthyThresholdCount: 3

Step 3: EC2 + Auto Scaling Group

Instead of launching individual EC2 instances, we use a Launch Template+ Auto Scaling Group (ASG) to automatically manage instance count.

Launch Template

Defines what to launch: AMI, instance type, security group, IAM role, and User Data (a startup script that runs on first boot).

Auto Scaling Group

Defines how many to launch: minimum, maximum, and desired count. It also handles replacement of unhealthy instances.

☁️ Azure Parallel

VMSS comparison: An Azure VMSS bundles the image and scaling config into one resource. AWS separates them: Launch Template (image config) + ASG (scaling config). Same result, different structure.

User Data Script

User Data is a bash script that runs when the instance first boots. We use it to install the CodeDeploy agent, Node.js, and set up environment variables.

bash
#!/bin/bash
# User Data — runs on first boot

# Install CodeDeploy Agent
yum install -y ruby wget
cd /tmp
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
chmod +x ./install && ./install auto

# Install Node.js
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs
npm install -g pm2

# Create environment file with RDS connection details
cat > /home/ec2-user/.env << EOF
NODE_ENV=production
PORT=3000
DB_HOST=your-rds-endpoint.rds.amazonaws.com
DB_PORT=5432
DB_NAME=aws_sandbox
DB_USER=dbadmin
DB_PASSWORD=YourPassword
EOF

Scaling Policies

Target Tracking scales based on a metric. We set CPUUtilization target to 70%— AWS adds instances when CPU exceeds 70% and removes them when it drops below.


🧪

Hands-On: Deploy Compute Stack and Test Load Balancing

After deploying stacks 1-5, test that the ALB distributes traffic:

bash
# Get ALB DNS name
ALB_DNS=$(aws cloudformation describe-stacks \
  --stack-name aws-sandbox-alb \
  --query 'Stacks[0].Outputs[?OutputKey==`ALBDNSName`].OutputValue' \
  --output text)

# Hit the info endpoint multiple times
# Watch the hostname change — that's load balancing!
for i in {1..5}; do
  echo "Request $i:"
  curl -s "http://$ALB_DNS/api/info" | python3 -c "
import sys,json
d=json.load(sys.stdin)
print(f"  Hostname: {d['hostname']}, CPUs: {d['cpus']}")"
  sleep 1
done

Each request should show 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 and patching
  • ALB + Target Group pattern is the standard for HTTP load balancing
  • Launch Template + ASG = reproducible, auto-healing, auto-scaling compute
  • User Data scripts are powerful but run only on first boot
  • The /health endpoint is critical — it's how the ALB knows which instances are alive