본문 바로가기

Python/Boto3

AWS Lambda를 통해 EC2 백업 자동화 구성하기

이전 글과 동일한 방법으로 구성합니다.

 

조금 더 상세한 설명은 위의 글을 참고해주세요

 

Cloudwatch Event + Lambda이기 때문에

 

알맞은 Role과 백업을 하고자 하는 시간대로 CloudWatch Event를 구성하겠습니다.

 

저는 아래와 같이 구성하였습니다.

 

 

 

람다 소스코드는 아래와 같습니다.

이번에는 환경 태그값에 따라서 백업을 하는 형태로 구성해봤습니다.

 

 

import boto3
import datetime

def backup_instances(client):    
    response = client.describe_instances()
    ec2_list = response['Reservations']  # 인스턴스 정보들

    for ec2 in ec2_list:
        ec2_info = ec2['Instances'][0]
        try:
            instance_name = [tag.get('Value') for tag in ec2_info['Tags'] if tag['Key'] == 'Name'][0]
            instance_env = [tag.get('Value') for tag in ec2_info['Tags'] if tag['Key'] == 'Env'][0]
        except:
            instance_name = ec2_info['InstanceId']
            instance_env = '-'

        # 운영계만 백업
        if instance_env == "PRD":
            print("     Name : {}".format(instance_name))
            print("      Env : {}".format(instance_env))

            # AMI 생성
            try:
                image = client.create_image(
                    InstanceId=ec2_info['InstanceId'],
                    Name="{}-backup-{}".format(instance_name, datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')),
                    Description="Automatic Daily Backup of {} from {}".format(instance_name, ec2_info['InstanceId']),
                    NoReboot=True,
                    DryRun=False
                )
                client.create_tags(Resources=[image['ImageId']], Tags=[{'Key': 'Name', 'Value': instance_name}])
                print("  New AMI : {}".format(image['ImageId']))
                
            except:
                print("Failure trying to create image or tag image. See/report exception below")
                exc_info = sys.exc_info()
                traceback.print_exception(*exc_info)

def lambda_handler(event, context):
    client = boto3.client('ec2')
    backup_instances(client)

 

일정 기간이 지난 AMI와 스냅샷에 대해서도 삭제하는 부분이 필요합니다.

따라서 아래와 같이 코드를 구성하여서 삭제할 수 있습니다.

default_retenteion_time은 일단위로 3일이 지난 AMI 및 Snapshot을 삭제하는 코드입니다.

 

default_retenteion_time = 3

def delete_expired_amis(client):
    print('Trying to delete Expired AMIs...')
    expire = datetime.datetime.now()-datetime.timedelta(days=default_retenteion_time)
    response = client.describe_images(Owners=['self'])
    amis = response['Images']

    names = []
    for ami in amis:
        if ami['CreationDate'][:10] <= expire.strftime('%Y-%m-%d'):
            names.append(ami['ImageId'])            
    for name in names:
        try:
            client.deregister_image( ImageId=name )
            print('Delete '+ name)
        except:
            print('Failure trying to delete '+name)

def delete_expired_snapshots(client):
    print('Trying to delete Expired AMIs...')
    expire = datetime.datetime.now()-datetime.timedelta(days=default_retenteion_time)
    response = client.describe_snapshots(OwnerIds=['self'])
    snapshots = response['Snapshots']
    names = []
    for snapshot in snapshots:
        if snapshot['StartTime'].strftime('%Y-%m-%d') <= expire.strftime('%Y-%m-%d'):
            names.append(snapshot['SnapshotId'])
                
    for name in names:
        try:
            client.delete_snapshot(SnapshotId = name)
            print('Delete : '+name)
        except Excetion as e:
            print('Failure trying to delete '+name)
            print(e)

 

여기까지 기본적으로 인프라를 구축하고 서버 스케줄링 및 백업까지 자동화를 구성하는 코드들을 알아봤습니다.

다음 포스트에서는 운영하면서 있으면 도움이 되는 람다함수를 만들어 보도록 하겠습니다.