7.1 What an AMI Contains: Snapshot, Boot Mode, Block Device Mappings
Right, let’s talk about what’s actually inside an AMI. It’s not just a magical box labeled “my server.” An AMI is more like a recipe and a set of ingredients. If you don’t understand the recipe, you’re going to end up with a culinary disaster, or in our case, an instance that either won’t boot or bills you for storage you never knew existed.
At its core, an AMI is a pointer. It’s not the data itself. It’s a JSON-like description that tells EC2, “Hey, when someone wants to launch an instance from me, here’s what you need to do.” This description primarily consists of three critical things: pointers to one or more EBS snapshots (the ingredients), the boot mode for the kernel, and a blueprint for how to assemble the disks—the Block Device Mappings.
The Snapshot: Your Root Volume’s Frozen Shadow
The most important part of an AMI is the EBS snapshot it references for the root volume. This snapshot is a frozen, point-in-time copy of your source instance’s root disk. When you launch an instance, EC2 creates a new EBS volume from this snapshot and attaches it as the root device. This is a crucial distinction: every new instance gets its own fresh copy of that volume. They don’t share it. This is why it’s fast—the snapshot is stored in S3, but the new volume is provisioned in your AZ almost instantly.
Think of the AMI as the cookie cutter and the snapshot as the dough. You can use the same cutter (AMI) a thousand times to make a thousand separate cookies (instances), all with the same shape.
You can see the snapshot ID an AMI uses by describing it. It’s buried in the block device mapping, which we’ll get to next.
# Get the details of a specific AMI
aws ec2 describe-images --image-ids ami-1234567890example --region us-east-1
Look for the SnapshotId field inside the BlockDeviceMappings array. This is the tangible asset you’re creating when you register an AMI. Pro Tip: If you delete an AMI, you are only deleting the pointer (the recipe). The underlying snapshots (the ingredients) are left behind, and you will continue to pay for them until you manually delete them. This is the number one way people accidentally run up their AWS bill. I’ve done it. You’ll probably do it. Let’s try not to.
Boot Mode: The Great UEFI vs. BIOS Debate
This one feels like it should be simple, but AWS had to go and make it interesting. The boot mode dictates how the underlying hardware hands off control to the operating system. You’ve got two main choices:
- legacy-bios: The old way. It’s been around forever and is universally compatible.
- uefi: The modern way. It allows for things like Secure Boot, which verifies the digital signature of every piece of software from the firmware up to the OS kernel, making it harder for rootkits to take hold.
Why should you care? Well, if you try to launch an AMI that was built as UEFI with Secure Boot enabled using the legacy-bios boot mode, it will fail spectacularly. The hardware won’t know how to talk to it. The reverse is also true.
The key is consistency. Your AMI inherits the boot mode from the instance you used to create it. When you describe an AMI, you can see its intended boot mode.
# The boot mode is in the describe-images output
aws ec2 describe-images --image-ids ami-1234567890example --query 'Images[0].BootMode' --output text
The Pitfall: You can’t change the boot mode of an AMI after it’s created. If you need to switch from BIOS to UEFI, you have to launch an instance from the old AMI, change its boot mode settings (this often involves converting the disk partition scheme, e.g., from MBR to GPT), and then create a brand new AMI from that instance. It’s a pain. So get it right the first time. For most new Linux workloads, uefi is the way to go.
Block Device Mappings: The Assembly Instructions
This is the blueprint. The Block Device Mapping (BDM) is the part of the AMI recipe that tells EC2 how to assemble the disks when it creates a new instance from this AMI. It answers questions like:
- “Which snapshot becomes the root volume (
/dev/sda1,/dev/xvda)?” - “Should I add any additional volumes at launch?”
- “How big should those volumes be, and what type (gp3, io2)?”
There are two types of BDMs, and confusing them is a classic rookie mistake:
- The AMI’s BDM: This is the template. It’s stored as part of the AMI metadata. It defines the default storage configuration for any instance launched from this AMI.
- The Instance’s BDM: This is what is actually used at launch. It can be a verbatim copy of the AMI’s BDM, or you can override it at launch time (e.g., “I know the AMI says 8 GB for the root, but for this instance, make it 50 GB”).
Here’s what the BDM for a simple AMI might look like in the describe-images output. It’s a JSON array that maps device names to snapshot IDs (for the root) or volume specifications (for additional volumes).
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-0668776717894f1b9",
"VolumeSize": 8,
"VolumeType": "gp2"
}
},
{
"DeviceName": "/dev/sdf",
"Ebs": {
"DeleteOnTermination": false,
"VolumeSize": 100,
"VolumeType": "gp3"
}
}
]
In this example, any instance launched from this AMI will, by default:
- Get a root volume from
snap-066877..., 8 GB gp2, that will be deleted when the instance is terminated. - Get a second, completely empty 100 GB gp3 volume attached as
/dev/sdf. BecauseDeleteOnTerminationisfalse, this volume will be left behind when the instance terminates. This is a fantastic way to accidentally lose track of resources and leak money. Always, always check the default BDM of your custom AMIs.
The DeviceName itself is largely a historical artifact. Just make sure it matches what the operating system in your snapshot expects. For most modern Linux AMIs, this is /dev/xvda or /dev/nvme0n1. If you get it wrong, your instance will fail its status checks because it can’t find its root device. It’s a small, finicky detail that causes disproportionately large headaches.