Lambda 함수와 CloudWatch를 이용하여 Daily 백업 및 삭제
- 추가사항
백업 대상
|
백업 주기
|
백업 시간
|
보관 주기
|
삭제 대상
|
삭제 주기
|
삭제 시간
|
기타
|
실행중인 EC2 Instances AMI, Volumes
|
매일
|
당일 새벽 5시
|
7일
|
생성 후 7일이 지난 AMI, Snapshots
|
매일
|
당일 새벽 6시
|
|
- 순서는 다음과 같습니다.
-
IAM 설정
-
Lambda 함수작성 및 테스트
-
CloudWatch 설정
IAM 설정
: AMI와 볼륨의 Snapshot을 위하여 EC2 Access를 허용하는 정책을 설정하여 줍니다.
1. 서비스에서 IAM을 클릭후 대쉬보드로 들어간 뒤 [역할] , [역할 만들기]를 차례대로 클릭하여 줍니다.
2. Lambda를 이용하여 자동백업, 삭제를 시행할 것이기에 [Lambda]서비스를 클릭한 후 아래의 [다음]을 누릅니다.
3. 다음 페이지의 [정책생성] 버튼을 클릭, 그 후 JSON탭을 누르면 보이는 기존의 코드를 지운 후 다음과 같은 코드를 넣어줍니다.
# IAM Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*"
}
]
}
4. 아래에 나오는 [정책검토] 버튼을 클릭한 후 설정값에 맞는 이름을 넣어 주고 아래의 [정책생성] 버튼을 클릭합니다.
5. 다시 처음의 IAM 대쉬보드에서 [역할], [역할만들기]를 재 클릭 해줍니다.
6. 정책에 만들어주었던 이름을 검색하여 선택한 후 아래의 [다음]버튼을 클릭합니다.
7. 역할 이름을 지정하여 줍니다. (태그 값은 지정하지 않고 넘어갔습니다.) 그 후 아래의 [역할 만들기] 버튼을 눌러줍니다.
8. 기존 검색창 리스트에 방금 만들어 논 역할이 보여지게 됩니다.
Lambda 함수 작성 및 테스트
: 사전에 실행 중 이던 EC2 인스턴스에 태그를 지정해 주어서 태그 값이 지정된 인스턴스만 백업이 진행되도록 하였습니다.
(Key : tag-key , Value : Backup)
1. 서비스의 Lambda 대쉬보드에 들어가 [함수생성] 버튼을 클릭하여 줍니다.
2. 이름을 지정 한 후 처음에 지정해주었던 IAM역할을 선택해 줍니다. 그 후 [함수생성] 버튼을 클릭합니다.
: Python 2.7 이용
3. 기존의 Default코드를 삭제한 후 다음과 같은 코드를 넣고 아래의 기본설정 제한시간을 1분으로 조정해 줍니다.
# Automated AMI Backups
#
# @author Robert Kozora <bobby@kozora.me>
#
# This script will search for all instances having a tag with "Backup" or "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',region_name='ap-northeast-2')
#image = ec.Image('id')
def lambda_handler(event, context):
reservations = ec.describe_instances(
Filters=[
{'Name': 'tag-key', 'Values': ['backup', 'Backup']},
]
).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
#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')
AMIid = ec.create_image(InstanceId=instance['InstanceId'], Name="Lambda - " + instance['InstanceId'] + " from " + create_fmt, Description="Lambda created AMI of instance " + instance['InstanceId'] + " from " + create_fmt, 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('%m-%d-%Y')
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': 'DeleteOn', 'Value': delete_fmt},
]
)
4. 상단에 [저장] 버튼을 누른 후 옆에 테스트 버튼을 눌러 테스트 파일을 만들고 테스트 버튼을 한번 더 눌러 실행시켜줍니다.
5. EC2 대시보드로 가서 AMI와 볼륨의 Snapshot이 제대로 작동되는지 확인하여 줍니다
CloudWatch 설정
: 지정된 시간에 함수를 트리거 하기 위하여 CloudWatch를 이용합니다.
1. 서비스항목에서 CloudWatch를 클릭하여 옆 대시보드에 [규칙] , [규칙생성]을 차례대로 클릭하여 줍니다.
2. 지정된 시간에 함수를 시행할 것이므로 [일정]탭으로 들어 간 후 [Cron식]으로 매일 새벽 5시에 백업시간을 지정해 줍니다. 그 후 옆에 연결할 Lambda함수를 좀전에 작성하였던 Backup함수를 지정해 줍니다.
: Cron식은 GMT시간으로 계산되기때문에 한국시간에서 -9시간을 해주면 됩니다.
Cron 식
00 20 ? * MON-SUN *
3. 아래에 [세부 정보 구성] 버튼을 클릭한 후 설정할 CloudWatch의 이름과 설명을 기술한 후 [규칙 생성] 버튼을 클릭합니다.
Scheduled Delete
주기적으로 삭제하는 방법도 Lambda함수코드와 Cron식만 달라지고 2,3번 항목에 대해선 동일한 방법으로 진행됩니다.
# Automated AMI and Snapshot Deletion
#
# @author Robert Kozora <bobby@kozora.me>
#
# This script will search for all instances having a tag with "Backup" or "backup"
# on it. 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-key', 'Values': ['backup', 'Backup']},
]
).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.startswith('Lambda - ' + instance['InstanceId']):
# print "FOUND IMAGE " + image.id + " FOR INSTANCE " + instance['InstanceId']
# Count this image's occcurance
imagecount = imagecount + 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, "%m-%d-%Y")
except IndexError:
deletion_date = False
delete_date = False
today_time = datetime.datetime.now().strftime('%m-%d-%Y')
# today_fmt = today_time.strftime('%m-%d-%Y')
today_date = time.strptime(today_time, '%m-%d-%Y')
# 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.endswith(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."
CleanUp Cron 식
00 21 ? * MON-SUN *
'AWS' 카테고리의 다른 글
AWS 기초시리즈 #4 - AWS VPC를 구성해보자 - VPC란? (1) | 2020.06.05 |
---|---|
AWS - Cloudwatch custom metric을 이용한 Monitoring (Memory, Disk 사용량 확인) (0) | 2020.06.04 |
AWS 기초시리즈 #3 - AWS IAM 계정생성 (0) | 2020.04.25 |
AWS 기초시리즈 #2 - AWS 가입, 계정 설정하기 (0) | 2020.04.24 |
AWS 기초시리즈 #1 - AWS 시작시 알아야 하는 용어 (0) | 2020.04.24 |