BespinGlobal에서 사용 중인 AMI로 EC2에 대한 AMI Backup을 매주 실행하는 Lambda Function 스크립트입니다.
# Automated AMI Backups # # @author Bobby Kozora # # This script will search for all instances having a tag with the name "backup" # and value "Backup" on it. As soon as we have the instances list, we loop # through each instance # and create an AMI of it. Also, it will look for a "Retention" tag key which # will be used as a retention policy number in days. If there is no tag with # that name, it will use a 7 days default value for each AMI. # # After creating the AMI it creates a "DeleteOn" tag on the AMI indicating when # it will be deleted using the Retention value and another Lambda function import boto3 import collections import datetime import sys import pprint ec = boto3.client('ec2') #image = ec.Image('id') def lambda_handler(event, context): reservations = ec.describe_instances(Filters=[ { 'Name': 'tag:Backup', 'Values': ['Weekly'] # 30일 마다 변경 할 때, 해당 Tag를 Monthly로 변경 }, ]).get('Reservations', []) instances = sum([[i for i in r['Instances']] for r in reservations], []) print("Found %d instances that need backing up" % len(instances)) to_tag = collections.defaultdict(list) for instance in instances: try: retention_days = [ int(t.get('Value')) for t in instance['Tags'] if t['Key'] == 'Retention' ][0] except IndexError: retention_days = 7 # 7일마다 Backup 하도록 일자 지정 #for dev in instance['BlockDeviceMappings']: # if dev.get('Ebs', None) is None: # continue # vol_id = dev['Ebs']['VolumeId'] # print "Found EBS volume %s on instance %s" % ( # vol_id, instance['InstanceId']) #snap = ec.create_snapshot( # VolumeId=vol_id, #) #create_image(instance_id, name, description=None, no_reboot=False, block_device_mapping=None, dry_run=False) # DryRun, InstanceId, Name, Description, NoReboot, BlockDeviceMappings create_time = datetime.datetime.now() create_fmt = create_time.strftime('%Y-%m-%d') Name_Tags = [result['Value'] for result in instance['Tags'] if result['Key'] == 'Name'][0]
AMIid = ec.create_image( InstanceId=instance['InstanceId'], Name= create_fmt + "_" + Name_Tags + " (" + instance['InstanceId'] + ")" + " / " + "Weekly", Description="Created with Lambda backup function", NoReboot=True, DryRun=False) pprint.pprint(instance) #sys.exit() #break #to_tag[retention_days].append(AMIid) to_tag[retention_days].append(AMIid['ImageId']) print("Retaining AMI %s of instance %s for %d days" % ( AMIid['ImageId'], instance['InstanceId'], retention_days, )) print(to_tag.keys()) 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 AMIs on %s" % (len(to_tag[retention_days]), delete_fmt)) #break ec.create_tags(Resources=to_tag[retention_days], Tags=[ { 'Key': 'Name', 'Value': create_fmt + "_" + Name_Tags }, { 'Key': 'DeleteOn', 'Value': delete_fmt }, ]) |
AMI Backup 된 것을 삭제 하는 것에 대한 Lambda Script
# Automated AMI and Snapshot Deletion # # @author Bobby Kozora # # This script will search for all instances having a tag named "Backup" with a value of "Backup". # As soon as we have the instances list, we loop through each instance # and reference the AMIs of that instance. We check that the latest daily backup # succeeded then we store every image that's reached its DeleteOn tag's date for # deletion. We then loop through the AMIs, deregister them and remove all the # snapshots associated with that AMI. import boto3 import collections import datetime import time import sys ec = boto3.client('ec2', 'ap-northeast-2') ec2 = boto3.resource('ec2', 'ap-northeast-2') images = ec2.images.filter(Owners=["self"]) def lambda_handler(event, context): reservations = ec.describe_instances(Filters=[ { 'Name': 'tag:Backup', 'Values': ['Weekly']}, # 30일 마다 변경 할 때, 해당 Tag를 Monthly로 변경 ] ).get( 'Reservations', [] ) instances = sum([[i for i in r['Instances']] for r in reservations], []) print("Found %d instances that need evaluated" % len(instances)) to_tag = collections.defaultdict(list) date = datetime.datetime.now() date_fmt = date.strftime('%Y-%m-%d') imagesList = [] # Set to true once we confirm we have a backup taken today backupSuccess = False # Loop through all of our instances with a tag named "Backup" for instance in instances: imagecount = 0 # Loop through each image of our current instance for image in images: # Our other Lambda Function names its AMIs Lambda - i-instancenumber. # We now know these images are auto created if image.name.endswith(" / " + "Weekly"): # print "FOUND IMAGE " + image.id + " FOR INSTANCE " + instance['InstanceId'] # Count this image's occcurance imagecount = imagecount + 1 # AMI Image 에 대해서 1개 이상일 때 1개를 남기고 삭제 try: if image.tags is not None: deletion_date = [ t.get('Value') for t in image.tags if t['Key'] == 'DeleteOn' ][0] delete_date = time.strptime(deletion_date, "%Y-%m-%d") except IndexError: deletion_date = False delete_date = False today_time = datetime.datetime.now().strftime('%Y-%m-%d') # today_fmt = today_time.strftime('%Y-%m-%d') today_date = time.strptime(today_time, '%Y-%m-%d') # If image's DeleteOn date is less than or equal to today, # add this image to our list of images to process later if delete_date <= today_date: imagesList.append(image.id) # Make sure we have an AMI from today and mark backupSuccess as true if image.name.startswith(date_fmt): # Our latest backup from our other Lambda Function succeeded backupSuccess = True print("Latest backup from " + date_fmt + " was a success") print("instance " + instance['InstanceId'] + " has " + str(imagecount) + " AMIs") print("=============") print("About to process the following AMIs:") print(imagesList) if backupSuccess == True: myAccount = boto3.client('sts').get_caller_identity()['Account'] snapshots = ec.describe_snapshots(MaxResults=1000, OwnerIds=[myAccount])['Snapshots'] # loop through list of image IDs for image in imagesList: print("deregistering image %s" % image) amiResponse = ec.deregister_image( DryRun=False, ImageId=image, ) for snapshot in snapshots: if snapshot['Description'].find(image) > 0: snap = ec.delete_snapshot( SnapshotId=snapshot['SnapshotId']) print("Deleting snapshot " + snapshot['SnapshotId']) print("-------------") else: print("No current backup found. Termination suspended.") |