EC2 Snapshots & AMIs
Create and restore EC2 snapshots and AMIs — AWS Cloud & DevOps with Python.
Focus: create and restore ec2 snapshots and amis
You've been running a fleet of EC2 instances for weeks, and now a developer wants to roll back a deployment to last week's state. Or worse — a misconfigured script just deleted a critical volume. If you haven't captured any snapshots, you're facing hours of reconfiguration and data loss. The good news? With AWS and Python, creating and restoring EC2 snapshots and AMIs is fast, scriptable, and can be automated into your DevOps workflow.
The problem this lesson solves
Manual backups are unreliable. You forget to run them, they take too long, and by the time you need them, they're outdated. In a production environment, you need a repeatable, automated way to protect your EC2 instances and their data. This lesson shows you how to use the AWS SDK for Python (boto3) to create snapshots of EBS volumes and build AMIs (Amazon Machine Images) — full, bootable backups of your instances. You'll then learn to restore from those snapshots and AMIs, turning a painful recovery process into a few lines of Python.
Core concept / mental model
Think of a snapshot as a photograph of your hard drive at a specific moment. It captures the exact state of an EBS volume — every file, every setting. An AMI is the whole camera: a template that contains the OS, the application, and all configuration needed to launch a new instance.
When you create an AMI from an EC2 instance, AWS automatically takes a snapshot of the root volume (and any other attached EBS volumes) and registers it as an AMI. Later, you launch a new instance from that AMI — it's an exact clone.
For data-only volumes, you don't need an AMI. You create a snapshot and later attach a restored volume to an existing instance. The key distinction: - Snapshot = backup of a single EBS volume (data) - AMI = full blueprint of an instance (bootable)
How it works step by step
-
Identify your resources — Get the instance ID, volume ID, or both. Python's
boto3gives you full control to list and filter. -
Create a snapshot — Call
create_snapshot()on the volume you want to back up. You can add aDescriptionto track what it is. -
Create an AMI — Call
create_image()on the instance. AWS will snapshot all attached volumes and register the AMI. -
Wait for completion — Snapshots and AMIs aren't instantly available. Poll their status until they're
completedoravailable. -
Restore — For snapshots, create a new volume from it and attach to an instance. For AMIs, launch a new instance using the AMI ID.
-
Clean up — When you're done, delete old snapshots and deregister AMIs to avoid storage costs.
Hands-on walkthrough
Prerequisites
Make sure you have boto3 installed and configured with credentials that have EC2 permissions (e.g., AmazonEC2FullAccess or scoped IAM policy).
pip install boto3
Example 1: Create a snapshot from a volume
import boto3
from datetime import datetime
# Replace with your volume ID
target_volume = 'vol-0a1b2c3d4e5f67890'
ec2 = boto3.client('ec2', region_name='us-east-1')
timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S')
snapshot = ec2.create_snapshot(
VolumeId=target_volume,
Description=f'Backup of {target_volume} at {timestamp}'
)
print(f"Snapshot created: {snapshot['SnapshotId']}")
Expected output:
Snapshot created: snap-0abcdef1234567890
Example 2: Create an AMI from an instance
import boto3
ec2 = boto3.client('ec2', region_name='us-east-1')
# Replace with your instance ID
instance_id = 'i-0a1b2c3d4e5f67890'
# Optional: list attached volumes to confirm what will be snapshot
volumes = ec2.describe_volumes(
Filters=[{'Name': 'attachment.instance-id', 'Values': [instance_id]}]
)['Volumes']
print(f"Found {len(volumes)} volume(s) attached")
ami = ec2.create_image(
InstanceId=instance_id,
Name=f'my-app-ami-{datetime.utcnow().strftime("%Y%m%d%H%M%S")}',
Description='Backup of my application server',
NoReboot=True # Avoid reboot during backup
)
print(f"AMI created: {ami['ImageId']}")
Example 3: Wait for snapshot to complete
import boto3
import time
snapshot_id = 'snap-0abcdef1234567890'
ec2 = boto3.resource('ec2', region_name='us-east-1')
snapshot = ec2.Snapshot(snapshot_id)
snapshot.wait_until_completed()
print("Snapshot is ready!")
Example 4: Restore a volume from a snapshot and attach it
import boto3
ec2 = boto3.client('ec2', region_name='us-east-1')
# Step 1: Create a new volume from the snapshot
new_volume = ec2.create_volume(
SnapshotId='snap-0abcdef1234567890',
AvailabilityZone='us-east-1a',
VolumeType='gp3'
)
volume_id = new_volume['VolumeId']
ec2.get_waiter('volume_available').wait(VolumeIds=[volume_id])
# Step 2: Attach the volume to an instance
instance_id = 'i-0a1b2c3d4e5f67890'
ec2.attach_volume(
Device='/dev/sdf',
InstanceId=instance_id,
VolumeId=volume_id
)
print(f"Restored volume {volume_id} attached to {instance_id}")
Creating the AMI from the snapshot to launch a restored EC2 instance
import boto3
ec2 = boto3.client('ec2', region_name='us-east-1')
# Step 1: Create a volume from a snapshot (as above)
new_volume = ec2.create_volume(SnapshotId='snap-0abcdef1234567890', AvailabilityZone='us-east-1a', VolumeType='gp3')
volume_id = new_volume['VolumeId']
ec2.get_waiter('volume_available').wait(VolumeIds=[volume_id])
# Step 2: Register the volume as an AMI (requires a snapshot of the root volume, which you have)
# In practice, you would use create_image from the instance, but for a pure volume you can build an AMI manually.
# For simplicity, we assume you already have an AMI ID from create_image.
ami_id = 'ami-0abcdef1234567890'
# Step 3: Launch a new instance from the AMI
response = ec2.run_instances(
ImageId=ami_id,
InstanceType='t2.micro',
KeyName='my-keypair',
SecurityGroupIds=['sg-0a1b2c3d4e5f67890'],
SubnetId='subnet-0a1b2c3d4e5f67890',
MinCount=1,
MaxCount=1
)
new_instance_id = response['Instances'][0]['InstanceId']
print(f"New instance launched: {new_instance_id}")
Compare options / when to choose what
| Feature | Snapshot | AMI |
|---|---|---|
| Scope | Single EBS volume | Entire instance (all volumes + metadata) |
| Use case | Back up data volumes, migrate data | Launch identical instances, scale out, disaster recovery |
| Bootable | No | Yes |
| Creation cost | Storage cost for snapshot data | Snapshot cost + AMI storage cost |
| Restore method | Create a new volume and attach | Launch a new EC2 instance |
| Typical automation frequency | High (daily scheduled) | Low (per deployment or release) |
When to choose snapshot: - You only need to back up a data volume (e.g., a database disk). - You want to keep costs low — snapshots are cheaper than full AMIs. - You need flexible restoration — you can attach the volume to an existing instance without launching a new one.
When to choose AMI: - You need to recover an entire instance, including its OS, app, and configuration. - You want to scale out by launching multiple identical instances. - You're doing blue/green deployments — launch a new instance from a known-good AMI.
Pro tip: For critical applications, use both: regular snapshots of data volumes for frequent backups, and AMIs for release-based versioning. This gives you granular recovery and full system restore capability.
Troubleshooting & edge cases
-
Snapshot stuck in
pendingstate — Large volumes take time. Use the waiter (wait_until_completed) or poll withdescribe_snapshots. If it never completes, check that your IAM role hasec2:CreateSnapshotpermission. -
AMI creation fails with
InvalidParameterValue— The instance must have a root volume that is an EBS volume, not an instance store. Check your instance type; some are instance-store backed and cannot be used withcreate_image. -
Can't attach a restored volume — The volume is created in a specific Availability Zone. You must attach it to an instance in the same AZ. Also, make sure the instance is running and the volume is
available. -
Snapshot/AMI costs blowing up — Storage is incremental, but you still pay for every snapshot. Automation should include lifecycle policies — delete old snapshots (e.g., keep last 7 days) and deregister old AMIs.
-
SSH key mismatch when launching from AMI — The AMI preserves the original key pair settings. If you want a new key, specify it during
run_instances. If the original key is gone, you might not be able to log in.
What you learned & what's next
You now understand the core idea behind create and restore EC2 snapshots and AMIs — how to back up volumes and entire instances programmatically with Python, then restore them when disaster strikes. You've also practiced waiting for resources, creating volumes, and launching instances — all core DevOps skills.
The next lesson in this track will likely cover automating snapshot rotation (deleting old backups) or infrastructure as code with Terraform/CloudFormation. With snapshots and AMIs in your toolkit, you're ready to build resilient, self-healing architectures.
Remember: backups are only useful if you can restore them. Always test your restore process in a sandbox environment before you need it in production.
Practice recap
Write a Python script that: (1) finds an instance by tag (e.g., Name=WebServer), (2) creates a snapshot of its root volume, (3) waits for completion, and (4) prints the snapshot ID. Then write a second script that creates a new volume from that snapshot and attaches it to a test instance. Run them in a non-production account to verify they work.
Common mistakes
- Forgetting to wait for snapshot completion before creating a volume — you'll get a 'snapshot not found' or 'invalid snapshot state' error. Always use
wait_until_completedor thevolume_availablewaiter. - Not specifying
NoReboot=Truewhen creating an AMI — Amazon may reboot the instance, causing downtime for users. SetNoReboot=Trueto avoid interruption (though consistency is slightly less guaranteed). - Attempting to attach a restored volume to an instance in a different Availability Zone — the volume must be created in the same AZ as the target instance, or you'll get an
InvalidAvailabilityZoneerror. - Skipping lifecycle management — without a cleanup script, snapshots and AMIs accumulate and you'll rack up unexpected storage costs. Automate deletion of older backups.
Variations
- Use
boto3.resourceinstead ofboto3.clientfor a more object-oriented approach (e.g.,ec2.create_snapshotreturns aSnapshotobject that you can callwait_until_completed()on). - Automate with AWS Lambda and
cron(EventBridge) to take scheduled snapshots of all tagged instances — great for serverless back-up-as-a-service. - Use
create_restore_image_taskto restore an AMI from an S3 bucket — useful for cross-account or disaster recovery scenarios.
Real-world use cases
- A nightly Python script snapshots all EBS volumes tagged with
Backup=truein a production EC2 fleet. - A blue/green deployment pipeline uses AWS CodeDeploy to create an AMI of the current app server, then launches a new instance from it for the green environment.
- A disaster recovery runbook restores a critical database by creating a new volume from a snapshot and attaching it to a standby EC2 instance in another Availability Zone.
Key takeaways
- Snapshots back up a single EBS volume — they're great for data recovery and are cheaper than full AMIs.
- AMI is a full, bootable blueprint of an instance — ideal for replicating servers or disaster recovery of an entire system.
- Always wait for the snapshot to complete (
wait_until_completed) before using it to create a volume or AMI. - Restore a snapshot by creating a new volume in the same Availability Zone and attaching it to an instance.
- Automate snapshot and AMI creation with boto3, but also automate cleanup to control costs.
- Test your restore process regularly — a backup you can't restore is useless.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.