πŸ§ͺ Hands-On Labs#

Practical exercises to reinforce your AWS knowledge. These labs use the AWS Free Tier wherever possible.


🏁 Getting Started#

  1. Create an AWS account (if you haven’t already)
  2. Set up IAM admin user with MFA (never use root!)
  3. Install AWS CLI and configure with your credentials
  4. Set a budget alert to avoid unexpected charges

Lab 1: IAM Users, Groups, and Policies#

Objective: Create IAM users, organize them into groups, and apply policies.

⚠️ Cost: Free (IAM has no cost)
⏱️ Time: 20 minutes

Steps:

  1. Create groups: Admins, Developers, Auditors
  2. Attach policies:
    • Admins β†’ AdministratorAccess
    • Developers β†’ AmazonEC2FullAccess, AmazonS3ReadOnlyAccess
    • Auditors β†’ ReadOnlyAccess
  3. Create IAM users and add to groups
  4. Create an IAM role for EC2 with S3 read access
# Create group
aws iam create-group --group-name Developers
aws iam attach-group-policy --group-name Developers \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess
aws iam attach-group-policy --group-name Developers \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Lab 2: Launch an EC2 Instance#

Objective: Launch and connect to an EC2 instance.

⚠️ Cost: ~$0.01/hr (t3.micro free tier eligible)
⏱️ Time: 20 minutes

Steps:

  1. Launch a t3.micro instance with Amazon Linux 2
  2. Create a key pair for SSH access
  3. Configure security group (SSH from your IP only)
  4. SSH into the instance
  5. Install a web server
# Launch instance
aws ec2 run-instances \
  --image-id resolve-ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64 \
  --instance-type t3.micro \
  --key-name my-key-pair \
  --security-groups web-sg \
  --user-data '#!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl enable httpd
    systemctl start httpd
    echo "<h1>Hello from EC2!</h1>" > /var/www/html/index.html'

# SSH into instance
ssh -i my-key-pair.pem ec2-user@<public-ip>

Lab 3: Create an S3 Bucket#

Objective: Create, configure, and manage an S3 bucket.

⚠️ Cost: Free tier eligible (5 GB storage)
⏱️ Time: 15 minutes

Steps:

  1. Create an S3 bucket with a globally unique name
  2. Upload objects (files, images)
  3. Enable versioning
  4. Configure lifecycle policy (transition to IA after 30 days)
  5. Enable static website hosting
  6. Generate a pre-signed URL
# Create bucket
aws s3 mb s3://my-unique-bucket-name-$(date +%s)

# Upload file
aws s3 cp hello.txt s3://my-bucket/

# Enable versioning
aws s3api put-bucket-versioning \
  --bucket my-bucket \
  --versioning-configuration Status=Enabled

# Generate pre-signed URL (valid for 1 hour)
aws s3 presign s3://my-bucket/hello.txt --expires-in 3600

Lab 4: Build a VPC from Scratch#

Objective: Create a custom VPC with public and private subnets.

⚠️ Cost: ~$0.05/hr (NAT Gateway is the main cost)
⏱️ Time: 30 minutes

Steps:

  1. Create VPC (10.0.0.0/16)
  2. Create public subnets in 2 AZs (10.0.1.0/24, 10.0.2.0/24)
  3. Create private subnets in 2 AZs (10.0.10.0/24, 10.0.11.0/24)
  4. Create and attach Internet Gateway
  5. Create NAT Gateway in public subnet
  6. Create route tables and associate subnets
  7. Launch EC2 in public subnet (verify internet access)
  8. Launch EC2 in private subnet (verify NAT access)

Lab 5: Set Up RDS Database#

Objective: Launch and connect to an RDS database.

⚠️ Cost: ~$0.02/hr (db.t3.micro free tier eligible)
⏱️ Time: 25 minutes

Steps:

  1. Create an RDS MySQL/PostgreSQL instance (db.t3.micro)
  2. Configure security group (allow your IP on port 3306/5432)
  3. Enable automated backups (7-day retention)
  4. Connect using MySQL Workbench or CLI
  5. Create a database and table
  6. Enable deletion protection
  7. Take a manual snapshot
# Create RDS instance
aws rds create-db-instance \
  --db-instance-identifier my-test-db \
  --db-instance-class db.t3.micro \
  --engine mysql \
  --master-username admin \
  --master-user-password 'MyP@ssword!' \
  --allocated-storage 20 \
  --backup-retention-period 7 \
  --deletion-protection \
  --vpc-security-group-ids sg-db-access

# Connect
mysql -h my-test-db.xxx.us-east-1.rds.amazonaws.com -u admin -p

Lab 6: Serverless API with Lambda + API Gateway + DynamoDB#

Objective: Build a fully serverless REST API.

⚠️ Cost: Free tier eligible (1M Lambda requests, 25 GB DynamoDB)
⏱️ Time: 30 minutes

Steps:

  1. Create DynamoDB table (On-Demand capacity)
  2. Create Lambda function with DynamoDB permissions
  3. Create HTTP API in API Gateway
  4. Connect API Gateway to Lambda
  5. Test the API endpoint
# Lambda function (index.py)
import json
import boto3
import uuid
from datetime import datetime

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('items')

def lambda_handler(event, context):
    if event['requestContext']['http']['method'] == 'GET':
        # List items
        response = table.scan()
        return {'statusCode': 200, 'body': json.dumps(response['Items']) }
    
    elif event['requestContext']['http']['method'] == 'POST':
        # Create item
        body = json.loads(event['body'])
        item = {'id': str(uuid.uuid4()), 'data': body['data'], 'created_at': datetime.now().isoformat() }
        table.put_item(Item=item)
        return {'statusCode': 201, 'body': json.dumps(item) }

Lab 7: Auto Scaling + Load Balancing#

Objective: Set up an auto-scaled, load-balanced web application.

⚠️ Cost: ~$0.05/hr (ALB + EC2 instances)
⏱️ Time: 30 minutes

Steps:

  1. Create launch template with web server user data
  2. Create target group with health check
  3. Create ALB
  4. Create Auto Scaling group (min: 2, max: 4)
  5. Configure scaling policy (CPU at 60%)
  6. Test by generating load
# Create launch template
aws ec2 create-launch-template \
  --launch-template-name web-template \
  --launch-template-data '{"ImageId": "ami-0abcdef1234567890", "InstanceType": "t3.micro", "SecurityGroupIds": ["sg-web"], "UserData": "'$(base64 -w0 userdata.sh)'" }'

# Create auto scaling group
aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name web-asg \
  --launch-template LaunchTemplateName=web-template \
  --min-size 2 --max-size 4 --desired-capacity 2 \
  --vpc-zone-identifier "subnet-abc,subnet-def" \
  --target-group-arns "arn:aws:...:targetgroup/web-tg/abc"

πŸ“š Additional Lab Resources#