Topic 2.1
EC2 Fundamentals: Instance Types, AMIs & User Data
In one line
An EC2 instance is a virtual machine built from an AMI (the disk image), sized by an instance type (CPU/memory/network), and configured at first boot by a user-data script.
Think of it like this
Renting a car. The AMI is the car MODEL with its factory setup (make, seats, radio presets); the INSTANCE TYPE is the engine size you pick (economy vs. truck); USER DATA is the note you leave for the valet — 'set the mirrors, load the luggage' — done once when you pick it up.
Key ideas
- 01
An AMI (Amazon Machine Image) is a snapshot of a root disk plus launch metadata. You start from an AWS-provided AMI (Amazon Linux 2023, Ubuntu) or build your own 'golden' AMI with your dependencies pre-installed so new instances boot faster and more predictably.
- 02
INSTANCE TYPES follow a naming pattern: family + generation + (processor) + size —
m7g.largeis general-purpose (m), 7th generation, Graviton ARM (g), large. Families:tburstable (cheap, CPU credits),mgeneral,ccompute-optimized,rmemory-optimized. Graviton (g) instances are typically ~20% cheaper per unit of performance, but any native dependencies (compiled Python wheels, Node native modules, JNI libraries) must have arm64 builds. - 03
t-family BURSTABLE instances earn CPU credits while idle and spend them under load. Sustained high CPU on at3either drains credits and throttles to baseline (standard mode) or silently bills extra (unlimited mode) — a classic surprise for workloads that aren't actually bursty. - 04
USER DATA is a script (or cloud-init config) that runs as root ONCE on first boot. It's how you install packages, pull config, and start your service without SSHing in. Its output lands in
/var/log/cloud-init-output.log— the first place to look when an instance boots but the app isn't running. - 05
Storage: the root volume is usually EBS (network-attached, persists independently, snapshot-able — Phase 4). Some types also have INSTANCE STORE (physically attached NVMe, very fast, but wiped when the instance stops). Pricing options — On-Demand, Savings Plans/Reserved, and Spot (spare capacity at up to ~90% off, reclaimable with a 2-minute warning) — are covered in Phase 7's cost topic.
Code & diagrams
# Latest Amazon Linux 2023 AMI via the public SSM parameter (no hardcoded AMI IDs)
AMI=$(aws ssm get-parameter \
--name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64 \
--query Parameter.Value --output text)
aws ec2 run-instances \
--image-id "$AMI" \
--instance-type t4g.small \
--iam-instance-profile Name=app-server \
--security-group-ids sg-0abc123 \
--subnet-id subnet-0def456 \
--metadata-options HttpTokens=required \
--user-data file://user-data.sh \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=api-1}]'Runs once, as root, on first boot. Keep it idempotent and short — heavy setup belongs in a pre-built AMI.
#!/bin/bash
set -euxo pipefail
dnf install -y docker
systemctl enable --now docker
# Pull config from SSM Parameter Store using the instance role (no keys)
DB_URL=$(aws ssm get-parameter --name /api/prod/db-url --with-decryption \
--query Parameter.Value --output text --region ap-south-1)
docker run -d --restart=always -p 80:8080 -e DB_URL="$DB_URL" \
123456789012.dkr.ecr.ap-south-1.amazonaws.com/api:1.4.2Explain it without notes
What does each part of c7g.xlarge tell you?
Your API runs on a t3.medium and becomes slow every afternoon, though nothing changed in the code. What's a likely EC2-specific cause?
Practice
Launch an instance with user data that installs nginx and writes the instance ID into index.html. How does the script find its own instance ID?
Why is looking up the AMI ID through an SSM public parameter better than hardcoding ami-0abc... in your script?
Trade-offs
- ↔
Heavy user-data scripts keep AMIs generic but make every boot slow and dependent on external repos being up; baked golden AMIs boot fast and consistently but require an image pipeline and regular rebuilds to stay patched.
Done when you can
I can decode an instance type name and pick a family for a workload.
I know the CPU-credit behaviour of
t-family instances.I can launch an instance with a role, IMDSv2, and user data from the CLI.
I know where to read user-data output when a boot goes wrong.