How to Schedule Daily Rolling EBS Snapshots Print

  • 0

First we need an IAM user with permissions only to do what our backup script requires. Create one in the IAM section of AWS console (I named mine snapshot-backup) and in the Inline Policies area give it the following policy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshot",
                "ec2:CreateTags",
                "ec2:DeleteSnapshot",
                "ec2:DescribeSnapshots",
                "ec2:DescribeTags"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

For the script itself we’ll need AWS command line tools:

1
2
3
4
5
6
7
8
sudo apt-get install awscli
 
# Follow the config documentation http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
aws configure --profile=ssbackup
AWS Access Key ID [None]: AAAAAAAAAAAAAAAAAA
AWS Secret Access Key [None]: bbbbbbbbbbbbbbbbbbbbbbbbbbbb
Default region name [None]: ap-southeast-2
Default output format [None]: json


My script will perform a snapshot of each volume passed to it, then delete any snapshots older than the given number of days. It will only delete snapshots that it created:

#!/usr/bin/env python3
#
# Creats a new snapshot for all passed volumes deletes old snapshots
#
# http://jayaraj.sosblogs.com/The-first-blog-b1/AWS-Automated-EBS-Snapshot-Script-b1-p3.htm
#
# Usage:
# python3 ssbackup.py --volume-ids=vol-1a23bcd4 --volume-ids=vol-2b34cde5 --expiry-days=7
#
 
import argparse
import subprocess
import json
import logging
import time, datetime, dateutil.parser
 
profile = 'ssbackup'       # Your AWS CLI profile
region = 'eu-west-1'  # AWS region volumes/snapshots are located
 
def bash(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    return process.communicate()[0].decode('utf-8')
 
def getOurSnapshots():
    """
        Return a list of snapshot Dicts created with this plugin.
    """
    return json.loads(bash([
            "aws", "ec2", "describe-snapshots",
            "--filters", "Name=tag-key,Values=Group", "Name=tag-value,Values=ssbackup",
            "--profile", profile,
            "--region", region,
            "--output=json"
        ]))['Snapshots']
 
def createSnapshots(volumeIds):
    """
        Return True if snapshots of the given volumes are created, else False
 
        Keyword arguments:
        volumeIds -- List of EBS volume IDs
    """
    # Create the snapshots
    snapshots = []
    for volumeId in volumeIds:
        snapshots.append(createSnapshotForVolume(volumeId))
 
    # Add Name and Group tags to the snapshot
    if len(snapshots):
        snapshotIds = []
        date = time.strftime("%Y-%m-%d")
 
        for snapshot in snapshots:
            snapshotIds.append(snapshot['SnapshotId'])
 
        # create-tags returns no output now so just perform the command and
        # return True
        bash([
            "aws", "ec2", "create-tags",
            "--resources", ' '.join(snapshotIds),
            "--tags", "Key=Name,Value='ahly-web-apps "+date+"'", "Key=Group,Value=ssbackup",
            "--profile", profile,
            "--region", region,
            "--output=json"
        ])
 
        return True
 
    return False
 
def createSnapshotForVolume(volumeId):
    """
        Return a Dict of a created snapshot for the given EBS volume
 
        Keyword arguments:
        volumeId -- An EBS volume ID
    """
 
    date = time.strftime("%Y-%m-%d")
    message = "Creating snapshot for volume "+volumeId+"..."
    response = json.loads(bash([
        "aws", "ec2", "create-snapshot",
        "--volume-id", volumeId,
        "--description", "Information-technology2017 "+date,
        "--profile", profile,
        "--region", region,
        "--output=json"
    ]))
    message += response['SnapshotId']
    logging.info(message)
 
    return response
 
def deleteOldSnapshots(snapshots, max_age):
    """
        Delete all listed snapshots older than max_age
    """
    snapshotIds = []
    date = datetime.datetime.now()
 
    for snapshot in snapshots:
        snapshotDate = dateutil.parser.parse(snapshot['StartTime']).replace(tzinfo=None)
        dateDiff = date - snapshotDate
 
        if dateDiff.days >= max_age:
            message = "Deleting snapshot "+snapshot['SnapshotId']+" ("+str(dateDiff.days)+" days old)..."
            # delete-snapshot no longer returns any output
            bash([
                "aws", "ec2", "delete-snapshot",
                "--snapshot-id", snapshot['SnapshotId'],
                "--profile", profile,
                "--region", region,
                "--output=json"
            ])
 
            message += "done"
            logging.info(message)
 
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='ADD YOUR DESCRIPTION HERE')
    parser.add_argument('-i','--volume-ids', help='EBS volume ID', required=True)
    parser.add_argument('-d','--delete-old', help='Delete old snapshots?', required=False, type=bool, default=True)
    parser.add_argument('-x','--expiry-days', help='Number of days to keep snapshots', required=False, type=int, default=7)
    args = parser.parse_args()
 
    logging.basicConfig(filename='Information-technology2017.log', level=logging.DEBUG, format='%(asctime)s:  %(message)s', datefmt='%Y-%m-%d %I:%M:%S%p')
 
    # Get all active volumes
    volumeIds = args.volume_ids.split(',')
    # Create the snapshots
    if len(volumeIds):
        snapshots = createSnapshots(volumeIds)
        pass
 
    # Delete snapshots older than expiry-days
    if args.delete_old:
        deleteOldSnapshots(getOurSnapshots(), args.expiry_days)



To run this script automatically each day, add it to your crontab like so:

1
2
# m   h  dom mon dow   command
  5   0    *   *   *   python3 /home/user/ssbackup.py --volume-ids=vol-a1bcd2e3 --expiry-days=7

 

The script will automatically create an ssbackup.log file that sits next to it describing exactly what it did on last run. For example here’s my log when running a backup with expiry-days=0 a couple of times:

1
2
3
4
2015-06-18 01:09:50AM:  Creating snapshot for volume vol-a1bcd2e3...snap-a123b4cd
2015-06-18 01:09:52AM:  Deleting snapshot snap-b123c4de (0 days old)...done
2015-06-18 02:36:28AM:  Creating snapshot for volume vol-a1bcd2e3...snap-c012345d
2015-06-18 02:36:30AM:  Deleting snapshot snap-a123b4cd (0 days old)...done





Was this answer helpful?

« Back