Skip to content

Amazon EBS - Elastic Block Store

Chapter 17: Amazon EBS - Elastic Block Store

Section titled “Chapter 17: Amazon EBS - Elastic Block Store”

Amazon EBS (Elastic Block Store) provides block-level storage volumes for use with EC2 instances.

EBS Overview
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | Amazon EBS | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Volumes | | Snapshots| | Types | |
| | | | | | | |
| | - Block | | - Backup | | - gp3 | |
| | Storage| | - S3 | | - io2 | |
| | - AZ | | - Regional| | - st1 | |
| | Level | | | | - sc1 | |
| +----------+ +----------+ +----------+ |
| |
| Volumes: Block storage attached to EC2 |
| Snapshots: Point-in-time backups stored in S3 |
| Types: Different performance characteristics |
| |
+------------------------------------------------------------------+

SSD-Based EBS Volumes
+------------------------------------------------------------------+
| |
| General Purpose SSD (gp3) - Latest Generation |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Boot volumes, general workloads | |
| | Size: 1 GB - 16 TB | |
| | Baseline IOPS: 3,000 (free) | |
| | Max IOPS: 16,000 | |
| | Baseline Throughput: 125 MB/s (free) | |
| | Max Throughput: 1,000 MB/s | |
| | Price: Lowest cost SSD | |
| | | |
| | Features: | |
| | - Independent IOPS and throughput configuration | |
| | - Volume cloning | |
| | - Multi-Attach not supported | |
| | | |
| +----------------------------------------------------------+ |
| |
| Provisioned IOPS SSD (io2) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Critical workloads, databases | |
| | Size: 4 GB - 16 TB | |
| | Max IOPS: 64,000 (256,000 with Block Express) | |
| | Max Throughput: 1,000 MB/s | |
| | Durability: 99.999% | |
| | | |
| | Features: | |
| | - Highest performance | |
| | - Multi-Attach (up to 16 instances) | |
| | - Block Express (NVMe) | |
| | | |
| +----------------------------------------------------------+ |
| |
| io2 Block Express |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Mission-critical, high-performance | |
| | Size: 4 GB - 64 TB | |
| | Max IOPS: 256,000 | |
| | Max Throughput: 4,000 MB/s | |
| | Latency: Sub-millisecond | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
HDD-Based EBS Volumes
+------------------------------------------------------------------+
| |
| Throughput Optimized HDD (st1) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Big data, data warehouses, logs | |
| | Size: 125 GB - 16 TB | |
| | Max Throughput: 500 MB/s | |
| | IOPS: Based on throughput (500 MB/s = ~500 IOPS) | |
| | Price: Lower than SSD | |
| | | |
| | Limitations: | |
| | - Cannot be boot volume | |
| | - Not suitable for random I/O | |
| | | |
| +----------------------------------------------------------+ |
| |
| Cold HDD (sc1) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Infrequently accessed data | |
| | Size: 125 GB - 16 TB | |
| | Max Throughput: 250 MB/s | |
| | Price: Lowest cost EBS | |
| | | |
| | Limitations: | |
| | - Cannot be boot volume | |
| | - Lower performance than st1 | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
EBS Volume Type Comparison
+------------------------------------------------------------------+
| |
| Type | Use Case | Max IOPS | Max Throughput | Boot |
| --------|-------------------|----------|----------------|-------|
| gp3 | General purpose | 16,000 | 1,000 MB/s | Yes |
| io2 | Critical workloads| 64,000 | 1,000 MB/s | Yes |
| io2 BE | Mission critical | 256,000 | 4,000 MB/s | Yes |
| st1 | Big data | ~500 | 500 MB/s | No |
| sc1 | Cold data | ~250 | 250 MB/s | No |
| |
+------------------------------------------------------------------+

EBS Multi-Attach
+------------------------------------------------------------------+
| |
| Purpose: Attach single volume to multiple EC2 instances |
| |
| Architecture: |
| +----------------------------------------------------------+ |
| | | |
| | +------------------+ | |
| | | io2 Volume | | |
| | | (Multi-Attach) | | |
| | +------------------+ | |
| | | | |
| | +----+----+----+----+ | |
| | | | | | | | |
| | v v v v v | |
| | +--+ +--+ +--+ +--+ +--+ | |
| | |EC2| |EC2| |EC2| |EC2| |EC2| (Up to 16 instances) | |
| | +--+ +--+ +--+ +--+ +--+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| Requirements: |
| +----------------------------------------------------------+ |
| | - io2 volume type | |
| | - Same AZ | |
| | - Cluster-aware file system (e.g., OCFS2, GFS2) | |
| | - Application must handle concurrent writes | |
| +----------------------------------------------------------+ |
| |
| Use Cases: |
| - High-availability clustering |
| - Shared storage for applications |
| - Oracle RAC, SAP HANA |
| |
+------------------------------------------------------------------+
EBS Snapshots
+------------------------------------------------------------------+
| |
| Snapshot Architecture |
| +----------------------------------------------------------+ |
| | | |
| | EBS Volume S3 (Snapshots) | |
| | +------------------+ +------------------+ | |
| | | | | | | |
| | | Block 1 | | Snapshot 1 | | |
| | | Block 2 |---->| (Incremental) | | |
| | | Block 3 | | | | |
| | | ... | +------------------+ | |
| | | | | | |
| | +------------------+ v | |
| | +------------------+ | |
| | | Snapshot 2 | | |
| | | (Incremental) | | |
| | | Only changed | | |
| | | blocks | | |
| | +------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| Features: |
| +----------------------------------------------------------+ |
| | - Incremental (only changed blocks) | |
| | - Point-in-time backup | |
| | - Cross-region copy | |
| | - Cross-account sharing | |
| | - Encryption support | |
| | - Can create volume from snapshot | |
| +----------------------------------------------------------+ |
| |
| Pricing: |
| +----------------------------------------------------------+ |
| | - Charged per GB-month of data stored | |
| | - No charge for first snapshot (full) | |
| | - Subsequent snapshots: only changed data | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
EBS Encryption
+------------------------------------------------------------------+
| |
| Encryption Scope: |
| +----------------------------------------------------------+ |
| | | |
| | Data encrypted at rest: | |
| | - Volume data | |
| | - Snapshots | |
| | - Volume copies | |
| | - Restored volumes | |
| | | |
| | Data encrypted in transit: | |
| | - Between EC2 and EBS | |
| | | |
| +----------------------------------------------------------+ |
| |
| Encryption Configuration: |
| +----------------------------------------------------------+ |
| | | |
| | Default Encryption: | |
| | - Enable at account level | |
| | - Applies to all new volumes | |
| | - Uses default KMS key or customer-managed key | |
| | | |
| | Per-Volume Encryption: | |
| | - Enable during volume creation | |
| | - Cannot change after creation | |
| | | |
| +----------------------------------------------------------+ |
| |
| KMS Integration: |
| +----------------------------------------------------------+ |
| | - AWS managed key (aws/ebs) | |
| | - Customer managed key (CMK) | |
| | - Key policies control access | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

EBS Performance Characteristics
+------------------------------------------------------------------+
| |
| IOPS (Input/Output Operations Per Second) |
| +----------------------------------------------------------+ |
| | | |
| | gp3: | |
| | - Baseline: 3,000 IOPS (included) | |
| | - Max: 16,000 IOPS (provisioned) | |
| | - IOPS can be configured independently | |
| | | |
| | io2: | |
| | - Provisioned IOPS | |
| | - Max: 64 IOPS per GB (up to 64,000) | |
| | | |
| | I/O Size: | |
| | - 16 KB = 1 IOPS | |
| | - 32 KB = 2 IOPS | |
| | - 64 KB = 4 IOPS | |
| | | |
| +----------------------------------------------------------+ |
| |
| Throughput (MB/s) |
| +----------------------------------------------------------+ |
| | | |
| | gp3: | |
| | - Baseline: 125 MB/s (included) | |
| | - Max: 1,000 MB/s (provisioned) | |
| | | |
| | st1: | |
| | - 40 MB/s per TB baseline | |
| | - 250 MB/s burst | |
| | - 500 MB/s max | |
| | | |
| | sc1: | |
| | - 12 MB/s per TB baseline | |
| | - 80 MB/s burst | |
| | - 250 MB/s max | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
EBS Burst Performance
+------------------------------------------------------------------+
| |
| gp3 Burst Balance |
| +----------------------------------------------------------+ |
| | | |
| | Burst Bucket: | |
| | - Accumulates when not using full IOPS | |
| | - Depletes when exceeding baseline | |
| | - 5.4 million I/O credits max | |
| | | |
| | Example: | |
| | - Baseline: 3,000 IOPS | |
| | - Burst: Up to 16,000 IOPS | |
| | - Duration: Based on credit balance | |
| | | |
| +----------------------------------------------------------+ |
| |
| st1/sc1 Burst Performance |
| +----------------------------------------------------------+ |
| | | |
| | Sustained: 40 MB/s per TB (st1) | |
| | Burst: 250 MB/s (st1) | |
| | | |
| | Example (1 TB st1): | |
| | - Sustained: 40 MB/s | |
| | - Burst: 250 MB/s | |
| | - Burst duration: Based on credit balance | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

# ============================================================
# EBS Volume
# ============================================================
resource "aws_ebs_volume" "data" {
availability_zone = "us-east-1a"
size = 100
type = "gp3"
# Performance configuration (gp3)
iops = 3000
throughput = 125
# Encryption
encrypted = true
kms_key_id = aws_kms_key.ebs.arn
# Tags
tags = {
Name = "data-volume"
}
}
# ============================================================
# Attach Volume to EC2
# ============================================================
resource "aws_volume_attachment" "data" {
device_name = "/dev/sdh"
volume_id = aws_ebs_volume.data.id
instance_id = aws_instance.web.id
# Prevent destruction during detachment
skip_destroy = false
}
# ============================================================
# EBS Snapshot
# ============================================================
resource "aws_ebs_snapshot" "backup" {
volume_id = aws_ebs_volume.data.id
description = "Backup snapshot"
tags = {
Name = "data-backup"
}
}
# ============================================================
# Snapshot Copy (Cross-Region)
# ============================================================
resource "aws_ebs_snapshot_copy" "dr" {
source_snapshot_id = aws_ebs_snapshot.backup.id
source_region = "us-east-1"
# Destination region
provider = aws.dr_region
# Encryption
encrypted = true
kms_key_id = aws_kms_key.ebs_dr.arn
tags = {
Name = "data-backup-dr"
}
}
# ============================================================
# EBS Volume from Snapshot
# ============================================================
resource "aws_ebs_volume" "restored" {
availability_zone = "us-east-1a"
snapshot_id = aws_ebs_snapshot.backup.id
type = "gp3"
size = 100
tags = {
Name = "restored-volume"
}
}
# ============================================================
# Provisioned IOPS Volume (io2)
# ============================================================
resource "aws_ebs_volume" "database" {
availability_zone = "us-east-1a"
size = 500
type = "io2"
# IOPS configuration
iops = 10000
# Multi-Attach enabled
multi_attach_enabled = true
encrypted = true
kms_key_id = aws_kms_key.ebs.arn
tags = {
Name = "database-volume"
}
}
# ============================================================
# EC2 Instance with EBS Volumes
# ============================================================
resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "m5.large"
availability_zone = "us-east-1a"
# Root volume
root_block_device {
volume_size = 50
volume_type = "gp3"
iops = 3000
throughput = 125
encrypted = true
kms_key_id = aws_kms_key.ebs.arn
delete_on_termination = true
}
# Additional EBS volumes
ebs_block_device {
device_name = "/dev/sdh"
volume_size = 100
volume_type = "gp3"
iops = 3000
throughput = 125
encrypted = true
kms_key_id = aws_kms_key.ebs.arn
delete_on_termination = false
}
tags = {
Name = "web-server"
}
}
# ============================================================
# Data Lifecycle Manager (DLM) - Automated Snapshots
# ============================================================
resource "aws_dlm_lifecycle_policy" "ebs_backup" {
description = "Daily EBS backup policy"
execution_role_arn = aws_iam_role.dlm.arn
state = "ENABLED"
policy_details {
resource_types = ["VOLUME"]
schedule {
name = "Daily backups"
# Backup at 2 AM UTC
create_rule {
interval = 24
interval_unit = "HOURS"
times = ["02:00"]
}
# Retain for 30 days
retain_rule {
count = 30
}
# Copy to DR region
copy_tags = true
}
target_tags = {
Backup = "true"
}
}
}
# ============================================================
# EBS Default Encryption
# ============================================================
resource "aws_ebs_default_kms_key" "default" {
key_arn = aws_kms_key.ebs.arn
}
resource "aws_ebs_encryption_by_default" "default" {
enabled = true
}

EBS Best Practices
+------------------------------------------------------------------+
| |
| 1. Volume Type Selection |
| +----------------------------------------------------------+ |
| | - gp3 for most workloads | |
| | - io2 for critical, high-IOPS workloads | |
| | - st1 for sequential reads (big data) | |
| | - sc1 for infrequently accessed data | |
| +----------------------------------------------------------+ |
| |
| 2. Performance Optimization |
| +----------------------------------------------------------+ |
| | - Pre-warm volumes (read entire volume before use) | |
| | - Use appropriate I/O scheduler | |
| | - Monitor with CloudWatch metrics | |
| | - Consider RAID for higher performance | |
| +----------------------------------------------------------+ |
| |
| 3. Backup Strategy |
| +----------------------------------------------------------+ |
| | - Regular snapshots | |
| | - Use DLM for automated backups | |
| | - Cross-region copy for DR | |
| | - Test restore procedures | |
| +----------------------------------------------------------+ |
| |
| 4. Security |
| +----------------------------------------------------------+ |
| | - Enable encryption by default | |
| | - Use customer-managed KMS keys | |
| | - Restrict snapshot permissions | |
| +----------------------------------------------------------+ |
| |
| 5. Cost Optimization |
| +----------------------------------------------------------+ |
| | - Right-size volumes | |
| | - Delete unused volumes | |
| | - Clean up old snapshots | |
| | - Use gp3 for cost savings over gp2 | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

EBS is the foundation of persistent storage for EC2. SREs deal with volume performance tuning, snapshot automation for DR, encryption compliance, and cost optimization of unused volumes daily.

EBS in DevOps/SRE
+------------------------------------------------------------------+
| |
| Key SRE Responsibilities: |
| 1. Volume type selection for workload performance |
| 2. Snapshot automation and DR testing |
| 3. Encryption enforcement (default encryption) |
| 4. Cost cleanup (orphaned volumes/snapshots) |
| 5. IOPS monitoring and burst credit tracking |
| |
+------------------------------------------------------------------+

Terminal window
# Install tools
sudo pacman -S aws-cli-v2 jq
# === Volume Management ===
# List all volumes with status
aws ec2 describe-volumes \
--query 'Volumes[*].{ID:VolumeId,Size:Size,Type:VolumeType,State:State,AZ:AvailabilityZone,IOPS:Iops}' \
--output table
# Find orphaned (unattached) volumes — cost waste!
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].{ID:VolumeId,Size:Size,Type:VolumeType,Created:CreateTime}' \
--output table
# === Snapshot Automation ===
#!/bin/bash
# ~/bin/ebs-snapshot.sh — Snapshot all tagged volumes
set -euo pipefail
VOLUMES=$(aws ec2 describe-volumes \
--filters Name=tag:Backup,Values=true \
--query 'Volumes[*].VolumeId' --output text)
for vol in $VOLUMES; do
echo "Snapshotting $vol..."
aws ec2 create-snapshot \
--volume-id "$vol" \
--description "Auto backup $(date +%Y-%m-%d)" \
--tag-specifications "ResourceType=snapshot,Tags=[{Key=AutoBackup,Value=true}]"
done
# === Disk Performance from Linux ===
# Check I/O stats on attached EBS
sudo pacman -S sysstat
iostat -x 1 5 # Extended I/O stats every 1s, 5 times
# Check if volume is using NVMe (Nitro instances)
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
nvme list # List NVMe devices (install: sudo pacman -S nvme-cli)

IssueCauseSolution
High latency on gp3Burst credits exhaustedMonitor BurstBalance, upgrade to io2 or provision more IOPS
Volume stuck in “attaching”Instance/volume AZ mismatchVolumes must be in same AZ as instance
Snapshot taking too longLarge volume, first snapshotFirst snapshot is full copy; subsequent are incremental
Can’t delete snapshotReferenced by AMIDeregister AMI first, then delete snapshot
Encryption errorKMS key policy issueVerify IAM role has kms:CreateGrant and kms:Decrypt

Anti-Pattern Best Practice
─────────────────────────────────────────────────────────────
❌ Using gp2 (old gen) ✅ Migrate to gp3 (20% cheaper,
better baseline)
❌ Not enabling default encryption ✅ Enable account-level EBS
encryption with CMK
❌ Never cleaning up snapshots ✅ Use DLM with retention policies
❌ Orphaned volumes after ✅ Tag volumes, audit monthly,
termination set delete_on_termination
❌ Ignoring burst credits ✅ Monitor BurstBalance metric,
provision IOPS if sustained

  1. Q: How would you migrate an unencrypted EBS volume to encrypted?

    • A: You cannot encrypt an existing unencrypted volume in-place. Steps: (1) Create snapshot of unencrypted volume, (2) Copy snapshot with encryption enabled (specify KMS key), (3) Create new encrypted volume from encrypted snapshot, (4) Detach old volume, attach new one, (5) Update mount points. Automate with aws ec2 copy-snapshot --encrypted.
  2. Q: gp2 vs gp3 — why should you migrate?

    • A: gp3 provides 3,000 IOPS and 125 MB/s baseline included (gp2 baseline is 100 IOPS/GB, so you need 1TB to get 3,000 IOPS). gp3 allows independent IOPS/throughput provisioning. gp3 is ~20% cheaper. Migration: create snapshot → restore as gp3, or modify volume type in-place with aws ec2 modify-volume.

Exam Tip

  1. Volume Types: gp3 (general), io2 (high IOPS), st1 (throughput), sc1 (cold)
  2. Multi-Attach: io2 only, up to 16 instances, same AZ
  3. Snapshots: Incremental, stored in S3, point-in-time
  4. Encryption: AES-256, KMS integration, cannot disable after creation
  5. IOPS: gp3 baseline 3,000, max 16,000; io2 max 64,000
  6. Throughput: gp3 max 1,000 MB/s; st1 max 500 MB/s
  7. AZ Scope: EBS volumes are AZ-specific
  8. HDD Volumes: Cannot be boot volumes, minimum 125 GB
  9. gp3: Independent IOPS and throughput configuration
  10. DLM: Data Lifecycle Manager for automated snapshots

Chapter 18: Amazon EFS - Elastic File System


Last Updated: March 2026