EC2 Instance Types and Selection
EC2 Instance Types and Selection
Amazon EC2 provides scalable computing capacity in the AWS cloud. Instance types vary by CPU, memory, storage, and networking.
Instance Type Families
| Family | Use Case | Example |
|---|---|---|
| T3/T3a | Burstable general purpose | t3.micro (2 vCPU, 1 GiB) |
| M5/M6i | General purpose, balanced | m5.large (2 vCPU, 8 GiB) |
| C5/C6g | Compute optimized | c5.xlarge (4 vCPU, 8 GiB) |
| R5/R6i | Memory optimized | r5.large (2 vCPU, 16 GiB) |
| I3 | Storage optimized | i3.xlarge (4 vCPU, 30.5 GiB) |
| G5 | GPU accelerated | g5.xlarge (4 vCPU, 16 GiB) |
Launch an EC2 Instance
# Launch a new EC2 instance
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.micro \
--key-name my-key-pair \
--security-group-ids sg-xxx \
--subnet-id subnet-xxx \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=WebServer}]' \
--user-data '#!/bin/bash
yum update -y
yum install httpd -y
systemctl start httpd
systemctl enable httpd
'
# List running instances
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,PublicIpAddress,Tags[?Key==`Name`].Value|[0]]' \
--output table
Instance Lifecycle
Pending → Running → Stopping → Stopped → Running
↘ Terminated
- Stop/Start: Instance moves to new hardware (public IP changes)
- Hibernate: RAM saved to EBS, faster restart
- Terminate: Instance destroyed (default EBS volumes deleted)
# Stop an instance
aws ec2 stop-instances --instance-ids i-xxx
# Start an instance
aws ec2 start-instances --instance-ids i-xxx
# Terminate an instance
aws ec2 terminate-instances --instance-ids i-xxx
EC2 Security Groups and Key Pairs
EC2 Security Groups and Key Pairs
Security Groups
Security groups act as virtual firewalls controlling inbound and outbound traffic.
# Create a security group
aws ec2 create-security-group \
--group-name web-server-sg \
--description "Web server security group" \
--vpc-id vpc-xxx
# Allow HTTP inbound
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
# Allow HTTPS inbound
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
# Allow SSH from specific IP only
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp \
--port 22 \
--cidr 203.0.113.0/32
# Allow all outbound (default)
aws ec2 authorize-security-group-egress \
--group-id sg-xxx \
--protocol -1 \
--cidr 0.0.0.0/0
# List security group rules
aws ec2 describe-security-groups --group-ids sg-xxx
Security Group Rules Summary
┌─────────────────────────────────────────────┐
│ Security Group │
├─────────────────────────────────────────────┤
│ Inbound Rules │
│ ┌──────┬──────┬─────────────┐ │
│ │ Port │ Proto│ Source │ │
│ ├──────┼──────┼─────────────┤ │
│ │ 22 │ TCP │ 203.0.113.x │ │
│ │ 80 │ TCP │ 0.0.0.0/0 │ │
│ │ 443 │ TCP │ 0.0.0.0/0 │ │
│ └──────┴──────┴─────────────┘ │
│ Outbound Rules (default: all allowed) │
│ ┌──────┬──────┬─────────────┐ │
│ │ ALL │ ALL │ 0.0.0.0/0 │ │
│ └──────┴──────┴─────────────┘ │
└─────────────────────────────────────────────┘
Key Pairs
# Create a key pair
aws ec2 create-key-pair --key-name my-key-pair --query 'KeyMaterial' --output text > my-key-pair.pem
# Set permissions (Linux/Mac)
chmod 400 my-key-pair.pem
# Connect via SSH
ssh -i my-key-pair.pem ec2-user@<public-ip>
# Use SSM Session Manager (no SSH needed)
aws ssm start-session --target i-xxx
EBS Storage Volumes
EBS Storage Volumes
Elastic Block Store provides persistent block storage for EC2 instances.
EBS Volume Types
| Type | Use Case | IOPS | Throughput | Size Range |
|---|---|---|---|---|
| gp3 | General purpose SSD | 3,000-16,000 | 125-1,000 MB/s | 1 GiB-16 TiB |
| gp2 | General purpose SSD | Up to 16,000 | Up to 250 MB/s | 1 GiB-16 TiB |
| io2 | High performance SSD | Up to 64,000 | Up to 1,000 MB/s | 4 GiB-16 TiB |
| st1 | Throughput HDD | 500 | 500 MB/s | 500 GiB-16 TiB |
| sc1 | Cold HDD | 250 | 250 MB/s | 500 GiB-16 TiB |
EBS Operations
# Create an EBS volume
aws ec2 create-volume \
--availability-zone us-east-1a \
--size 100 \
--volume-type gp3 \
--iops 3000 \
--throughput 125 \
--tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=DataVolume}]'
# Attach a volume to an instance
aws ec2 attach-volume \
--volume-id vol-xxx \
--instance-id i-xxx \
--device /dev/sdf
# On the instance, mount the volume:
# sudo mkfs -t ext4 /dev/nvme1n1
# sudo mkdir /data
# sudo mount /dev/nvme1n1 /data
# Create a snapshot
aws ec2 create-snapshot \
--volume-id vol-xxx \
--description "Daily backup" \
--tag-specifications 'ResourceType=snapshot,Tags=[{Key=Backup,Value=Daily}]'
# List snapshots
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[*].[SnapshotId,VolumeId,State,StartTime]' --output table
EBS Encryption
# Enable encryption by default for your account
aws ec2 enable-ebs-encryption-by-default
# Create an encrypted volume
aws ec2 create-volume \
--availability-zone us-east-1a \
--size 100 \
--volume-type gp3 \
--encrypted \
--kms-key-id alias/aws/ebs
AMIs and User Data
AMIs and User Data
Amazon Machine Images (AMIs)
AMIs provide the information required to launch an instance. They contain a root volume template, launch permissions, and block device mappings.
# Find Amazon Linux 2 AMI
aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=amzn2-ami-hvm-*-x86_64-gp2" \
--query 'sort_by(Images,&CreationDate)[-1].ImageId' \
--output text
# Create an AMI from a running instance
aws ec2 create-image \
--instance-id i-xxx \
--name "MyApp-AMI-$(date +%Y%m%d)" \
--description "Custom AMI for web application"
# Share an AMI with another account
aws ec2 modify-image-attribute \
--image-id ami-xxx \
--launch-permission 'Add=[{UserId=123456789012}]'
User Data Scripts
User data scripts run on first boot. Use them to automate instance configuration:
#!/bin/bash
yum update -y
yum install -y httpd php
# Configure Apache
echo '<html><body><h1>Hello from EC2!</h1></body></html>' > /var/www/html/index.html
systemctl start httpd
systemctl enable httpd
# Install CloudWatch agent
yum install -y amazon-cloudwatch-agent
# Signal CloudFormation (if used)
/opt/aws/bin/cfn-signal -e $? --stack my-stack --resource WebServer --region us-east-1
Launch Templates
# Create a launch template
aws ec2 create-launch-template \
--launch-template-name MyWebTemplate \
--version-description "Version 1" \
--launch-template-data '{
"ImageId": "ami-xxx",
"InstanceType": "t3.micro",
"KeyName": "my-key-pair",
"SecurityGroupIds": ["sg-xxx"],
"UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQ==",
"BlockDeviceMappings": [{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 30,
"VolumeType": "gp3",
"Encrypted": true
}
}]
}'
Auto Scaling and Load Balancing
Auto Scaling Groups and Load Balancing
Auto Scaling Group (ASG)
ASGs automatically adjust the number of EC2 instances based on demand.
# Create a launch template
aws ec2 create-launch-template \
--launch-template-name asg-template \
--launch-template-data '{
"ImageId": "ami-xxx",
"InstanceType": "t3.micro",
"SecurityGroupIds": ["sg-xxx"]
}'
# Create an Auto Scaling Group
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name my-asg \
--launch-template LaunchTemplateName=asg-template \
--min-size 2 \
--max-size 10 \
--desired-capacity 2 \
--vpc-zone-identifier "subnet-xxx,subnet-yyy" \
--target-group-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/xxx
# Configure scaling policy
aws autoscaling put-scaling-policy \
--auto-scaling-group-name my-asg \
--policy-name cpu-target-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
},
"TargetValue": 70.0
}'
Application Load Balancer (ALB)
# Create an ALB
aws elbv2 create-load-balancer \
--name my-alb \
--type application \
--subnets subnet-xxx subnet-yyy \
--security-groups sg-xxx
# Create a target group
aws elbv2 create-target-group \
--name my-targets \
--protocol HTTP \
--port 80 \
--vpc-id vpc-xxx \
--health-check-path /health
# Create a listener
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:xxx:loadbalancer/app/my-alb/xxx \
--protocol HTTP \
--port 80 \
--default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:xxx:targetgroup/my-targets/xxx
Architecture Diagram
┌──────────────┐
│ Internet │
└──────┬───────┘
│
┌──────▼───────┐
│ ALB │
└──────┬───────┘
│
┌────────────┼────────────┐
│ │ │
┌─────▼─────┐┌────▼────┐┌─────▼─────┐
│ EC2 ││ EC2 ││ EC2 │
│ (AZ-1a) ││ (AZ-1b)││ (AZ-1c) │
└───────────┘└─────────┘└───────────┘
EC2 Pricing Optimization
EC2 Pricing Optimization
Instance Purchase Options
| Option | Discount | Commitment | Best For |
|---|---|---|---|
| On-Demand | None | None | Dev/test, unpredictable |
| Reserved (1yr) | ~40% | 1 year | Steady-state workloads |
| Reserved (3yr) | ~60% | 3 years | Predictable long-term |
| Spot | Up to 90% | None | Batch, fault-tolerant |
| Savings Plans | Up to 72% | $/hr commitment | Flexible across families |
Spot Instance Strategy
# Launch a Spot Instance
aws ec2 run-instances \
--image-id ami-xxx \
--instance-type c5.xlarge \
--instance-market-options '{
"MarketType": "spot",
"SpotOptions": {
"MaxPrice": "0.05",
"SpotInstanceType": "one-time",
"InstanceInterruptionBehavior": "terminate"
}
}'
# Request Spot Fleet
aws ec2 request-spot-fleet \
--spot-fleet-request-config '{
"IamFleetRole": "arn:aws:iam::xxx:role/aws-ec2-spot-fleet-tagging-role",
"TargetCapacity": 5,
"InstanceInterruptionBehavior": "terminate",
"LaunchSpecifications": [{
"ImageId": "ami-xxx",
"InstanceType": ["c5.xlarge", "c5a.xlarge", "m5.xlarge"]
}]
}'
Cost Monitoring
# Get current EC2 costs
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=SERVICE \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Elastic Compute Cloud - Compute"]}}'
# Find underutilized instances
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-xxx \
--start-time 2024-01-01T00:00:00Z \
--end-time 2024-01-31T23:59:59Z \
--period 86400 \
--statistics Average
Rightsizing Recommendations
# Get AWS Compute Optimizer recommendations
aws compute-optimizer get-ec2-instance-recommendations \
--instance-arns arn:aws:ec2:us-east-1:xxx:instance/i-xxx