この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
サーモン大好き横山です。
今回「 インフィニットループ×クラスメソッド×クリプトン合同勉強会 」で発表させていただきました。
ブログ記事、【お知らせ】1クリックで毎日スナップショットを自動取得 〜 ソンナコトモアロウカト v1.4 リリース から、Auto Scalingで制御しているEC2の部分をAWS Lambdaに置き換えた話をしました。
発表資料
[slideshare id=55766232&doc=awslambda-151203041554-lva1-app6891]
補足
今回のデモで「予め作っておいたAWS Lambdaがこちら」となっていた部分を補足致します。
デモでは、 Event soucesを rate(10 minutes)
で、PythonコードのBACKUP_RETENTIONは { 'minutes': 30 }
で設定していました。
この部分を Event soucesを cron(0 15 ? * * *)
でPythonコードのBACKUP_RETENTIONは { 'days': 7 }
で設定をしますとソンナコと同じように動作することが出来ます。
AWS Lambda作成
大まかな手順としまして以下のとおり通りです。
- 「Select blueprint」で
hello-world-python
を選択 - IAM RoleをPowerUserRoleと同じものを設定
- 「Lambda function code」にコードをコピー&ペースト
- 「Event sources」で「Scheduled Event」を
rate(10 minutes)
細かな設定方法は、 AWS LambdaからPythonでEC2のインスタンスを起動するスケジュールを設定してみた #reinvent に詳しく書いていますのでこちらをご参照ください。
使用したIAM Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
}
]
}
ソースコード
#!/usr/bin/env python
# encoding: utf-8
from __future__ import print_function
from datetime import datetime, timedelta
import time
import boto3
import pprint
BACKUP_RETENTION = {
'days': 7,
}
dt_now = datetime.now()
dt_backup_retention = dt_now + timedelta(**BACKUP_RETENTION)
def output_log(title, body):
print('----------[{}]----------'.format(title))
pprint.pprint(body)
print('-'*(22+len(title)))
def create_snapshot_ebs(ec2):
describe_volumes = ec2.describe_volumes()
output_log('describe_volumes', describe_volumes)
volume_ids = [ volume['VolumeId'] for volume in describe_volumes['Volumes'] ]
describe_tags = ec2.describe_tags(Filters=[
{
'Name': 'resource-type',
'Values': [ 'volume' ],
},
{
'Name': 'resource-id',
'Values': volume_ids
},
{
'Name': 'key',
'Values': [ 'Backup' ],
}
])
output_log('describe_tags',describe_tags)
create_snapshots = []
for tag in describe_tags['Tags']:
if tag['Value'] != 'true':
continue
instance_ids = [ attachment['InstanceId'] for attachment in volume['Attachments']
for volume in describe_volumes['Volumes']
if volume['VolumeId'] == tag['ResourceId'] ]
if not instance_ids:
continue
tag['InstanceId'] = instance_ids[0]
tag['DateCurrent'] = dt_now.strftime('%Y-%m-%d')
description = "ec2ab_{ResourceId}_{DateCurrent} ({InstanceId})".format(**tag)
create_snapshot = ec2.create_snapshot(
VolumeId=tag['ResourceId'],
Description=description
)
create_snapshots.append(create_snapshot)
output_log('create_snapshot[{}]'.format(description), create_snapshot)
unixtime = str(int(time.mktime(dt_backup_retention.timetuple())))
ec2.create_tags(
Resources = [ snapshot['SnapshotId'] for snapshot in create_snapshots ],
Tags = [
{ 'Key': 'PurgeAllow', 'Value': 'true' },
{ 'Key': 'PurgeAfter', 'Value': unixtime },
],
)
def purge_snapshot_ebs(ec2):
describe_tags = ec2.describe_tags(Filters=[
{
'Name': 'resource-type',
'Values': [ 'snapshot' ],
},
{
'Name': 'key',
'Values': [ 'PurgeAllow', 'PurgeAfter' ],
}
])
output_log('describe_tags(purge)', describe_tags)
snapshot_id_groups = {}
for tag in describe_tags['Tags']:
groups_key = tag['ResourceId']
if snapshot_id_groups.has_key(groups_key):
snapshot_id_groups[groups_key].append(tag)
else:
snapshot_id_groups[groups_key] = [tag]
for key, values in snapshot_id_groups.items():
tag_values = { v['Key']: v['Value'] for v in values
if v['Key'] in ['PurgeAllow', 'PurgeAfter']}
if len(tag_values) != 2:
continue
if tag_values['PurgeAllow'] != 'true':
continue
dt_purgeafter = datetime.fromtimestamp(int(tag_values['PurgeAfter']))
output_log('dt', [dt_now, dt_backup_retention, dt_purgeafter])
if dt_now > dt_purgeafter:
output_log('delete snapshot: {}'.format(key), values)
ec2.delete_snapshot(
SnapshotId=key
)
def handler():
ec2 = boto3.client('ec2')
create_snapshot_ebs(ec2)
purge_snapshot_ebs(ec2)
def lambda_handler(event, context):
handler()
おわりに
今回”ソンナコ”をテーマにAWS Lambdaに書き換えて見ましたが、他にもEC2で処理している部分をAWS Lambdaに置き換える事が可能だと思います。
これからも機会を見つけてブログや勉強会で発信していきたいです。
でもまずは、AWS LambdaのCFn対応が一番待ち遠しいです。