IaaS gives you virtual machines in the cloud with pay-per-use pricing, elastic scaling, and a massive ecosystem of managed services around them. This is where most professional production workloads live.
A cloud VM with configurable CPU, RAM, storage, and networking. You choose the OS, install what you want, and pay by the hour/second.
Pre-configured OS snapshots. You can use official images (Ubuntu 22.04) or create custom ones with your software pre-installed (golden images).
Virtual firewalls controlling inbound/outbound traffic to your instances. Stateful — if you allow inbound on port 443, the response traffic is automatically allowed.
Your own isolated network in the cloud. You define subnets (public/private), route tables, and internet gateways. Instances in private subnets can't be reached from the internet directly.
# Prerequisites: AWS CLI installed, credentials configured
# aws configure (set access key, secret, region)
# 1. Create a key pair for SSH access
aws ec2 create-key-pair --key-name myapp-key --query 'KeyMaterial' \
--output text > ~/.ssh/myapp-key.pem
chmod 400 ~/.ssh/myapp-key.pem
# 2. Create a security group
aws ec2 create-security-group \
--group-name myapp-sg \
--description "Web server security group"
# Allow SSH, HTTP, HTTPS
aws ec2 authorize-security-group-ingress --group-name myapp-sg \
--protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-name myapp-sg \
--protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-name myapp-sg \
--protocol tcp --port 443 --cidr 0.0.0.0/0
# 3. Launch the instance
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.micro \
--key-name myapp-key \
--security-groups myapp-sg \
--count 1 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=myapp-web}]'
# 4. Get the public IP
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=myapp-web" \
--query 'Reservations[0].Instances[0].PublicIpAddress' --output text
# 5. SSH in
ssh -i ~/.ssh/myapp-key.pem ubuntu@INSTANCE_IP
| Family | Optimized For | Example | Use Case |
|---|---|---|---|
| t3/t4g | Burstable general purpose | t3.micro (2 vCPU, 1GB) | Low-traffic web apps, dev |
| m6i/m7g | Balanced compute/memory | m6i.large (2 vCPU, 8GB) | General web apps |
| c6i/c7g | Compute-intensive | c6i.xlarge (4 vCPU, 8GB) | API servers, batch processing |
| r6i/r7g | Memory-intensive | r6i.large (2 vCPU, 16GB) | Caching, in-memory DBs |
| Graviton (g suffix) | ARM-based, 20% cheaper | t4g.micro | Everything (if your app supports ARM) |
Auto Scaling automatically adjusts the number of instances based on demand:
# Conceptual flow:
# 1. Create a Launch Template (defines instance config)
# 2. Create an Auto Scaling Group (min/max/desired instances)
# 3. Attach scaling policies (CPU > 70% → add instance)
# 4. Attach to a Load Balancer (distributes traffic)
# CloudWatch alarm triggers scaling:
# CPU > 70% for 5 minutes → scale out (add instances)
# CPU < 30% for 10 minutes → scale in (remove instances)