Scheduling EBS Snapshots using EC2 tags

I wanted a quick and (not so) dirty way to schedule backups of specific EBS volumes with a backup retention policy.

Oddly enough, this is not part of the basic services AWS offers, but I stumbled upon the great blog post from @ryan_sb.

His solution to use AWS Lambda and CloudWatch cron scheduling is great, but I needed to backup only specific EBS volumes and not all the volumes from a specific instance, so I shamelessly destroyed forked the original backup script.

To delete old EBS snapshots, the ebs-snapshots-janitor code can still be used as-is.

If you want to only snapshot specific EBS volumes, follow the instructions from the original solution, but replace the code from the original article by this:

# Original solution by @ryan_sb from serverlesscode.com, modified by @gferon for a different use-case
import boto3
import collections
import datetime
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
    volumes = ec2.describe_volumes(
        Filters=[
            {'Name': 'tag-key', 'Values': ['backup', 'Backup']},
        ]
    ).get(
        'Volumes', []
    )
    print "Found %d volumes that need backing up" % len(volumes)
    to_tag = collections.defaultdict(list)
    for volume in volumes:
        try:
            retention_days = [
                int(t.get('Value')) for t in volume['Tags']
                if t['Key'] == 'Retention'][0]
        except IndexError:
            retention_days = 7
        vol_id = volume['VolumeId']
        instance_id = volume['Attachments'][0]['InstanceId']
        print "Found EBS volume %s from instance %s" % (vol_id, instance_id)
        snap = ec2.create_snapshot(
            VolumeId=vol_id,
        )
        to_tag[retention_days].append(snap['SnapshotId'])
        print "Retaining snapshot %s of volume %s from instance %s for %d days" % (
            snap['SnapshotId'], vol_id, instance_id, retention_days)
    for retention_days in to_tag.keys():
        delete_date = datetime.date.today() + datetime.timedelta(days=retention_days)
        delete_fmt = delete_date.strftime('%Y-%m-%d')
        print "Will delete %d snapshots on %s" % (len(to_tag[retention_days]), delete_fmt)
        ec2.create_tags(
            Resources=to_tag[retention_days],
            Tags=[
                {'Key': 'DeleteOn', 'Value': delete_fmt},
            ]
        )

I can now rest.


Gabriel Féron

Yet-to-be successful software developer, crazy Android lover and open-source enthusiast