AWS EBSのスナップショットの「自動取得」と「指定の世代までの管理」を実施できる手順について記載しています。
1.インスタンスに「名前」と「世代管理用」のタグを設定します。
1-1.[ EC2 > インスタンス > インスタンス ] を表示します。
1-2.『タグ』タブを表示し【 タグの追加/編集 】をクリックします。
1-3.表示された『タグの追加/編集』画面で【 タグの作成 】をクリックすると行が追加されます。
1-4.適当な値を入力して【 保存 】をクリックします。
| キー | 値 |
|---|---|
| Name | ※適当な名前入力 |
| Backup-Generation | 2 |
※「Backup-Generation」キーで指定している値が「世代管理」数となります。
1.Lambdaで関数を作成します。
1-1.[ Lambda ]を表示します。
1-2.【 関数の作成 】をクリックします。
2.設計図の選択します。
2-2.表示された[ lambda-canary ]をクリックします。
3.「基本的な情報」を設定します。
3-1.『名前』を入力し、『ロール』から [ カスタムロールの作成 ] を選択します。

3-2.『ロールの作成』タブが作成されます。

3-3.『ロール名』に値を入力し、ポリシードキュメントの【 編集 】をクリックします。

3-4.ダイアログが表示されます。【 OK 】をクリックします。

3-5.ポリシードキュメントが編集可能となったら以下のコードに差し替え後、【 許可 】をクリックします。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeSnapshots",
"ec2:CreateSnapshot",
"ec2:DeleteSnapshot"
],
"Resource": [
"*"
]
}
]
}
『Lambda』画面に戻り、既存のロールに先ほど作成したロールが適用されます。

4.「cloudwatch-events」を設定します。

4-1.以下の値を設定します。

| ルール | 新規ルールの作成 |
| ルール名 | snapshot |
| ルールの説明 | ※任意 |
| ルールタイプ | スケジュール式 |
| スケジュール式 | cron(0 15 * * ? *) |
| トリガーの有効化 | 有効 |
※スケジュール式:日本時間 00:00 に実行
5.「Lambda関数コード」を設定します。

| 環境変数 | ※未構成 |
| 保管時に暗号化するKMSキー | (デフォルト)aws/lambda |
※環境変数をすべて削除します。
6.関数を作成します。
【 関数の作成 】をクリックします。

7.関数コードを設定します。
7-1.「設定」タブを選択し、関数コードを以下のコードと差し替えて【 保存 】をクリックします。

import boto3
import collections
import time
from botocore.client import ClientError
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
descriptions = create_snapshots()
delete_old_snapshots(descriptions)
def create_snapshots():
instances = get_instances(['Backup-Generation'])
descriptions = {}
for i in instances:
tags = {t['Key']: t['Value'] for t in i['Tags']}
generation = int(tags.get('Backup-Generation', 0))
if generation < 1:
continue
for b in i['BlockDeviceMappings']:
if b.get('Ebs') is None:
continue
volume_id = b['Ebs']['VolumeId']
description = volume_id if tags.get('Name') is '' else '%s(%s)' % (volume_id, tags['Name'])
description = 'Auto Snapshot ' + description
snapshot = _create_snapshot(volume_id, description)
print 'create snapshot %s(%s)' % (snapshot['SnapshotId'], description)
descriptions[description] = generation
return descriptions
def get_instances(tag_names):
reservations = ec2.describe_instances(
Filters=[
{
'Name': 'tag-key',
'Values': tag_names
}
]
)['Reservations']
return sum([
[i for i in r['Instances']]
for r in reservations
], [])
def delete_old_snapshots(descriptions):
snapshots_descriptions = get_snapshots_descriptions(descriptions.keys())
for description, snapshots in snapshots_descriptions.items():
delete_count = len(snapshots) - descriptions[description]
if delete_count <= 0:
continue
snapshots.sort(key=lambda x: x['StartTime'])
old_snapshots = snapshots[0:delete_count]
for s in old_snapshots:
_delete_snapshot(s['SnapshotId'])
print 'delete snapshot %s(%s)' % (s['SnapshotId'], s['Description'])
def get_snapshots_descriptions(descriptions):
snapshots = ec2.describe_snapshots(
Filters=[
{
'Name': 'description',
'Values': descriptions,
}
]
)['Snapshots']
groups = collections.defaultdict(lambda: [])
{groups[s['Description']].append(s) for s in snapshots}
return groups
def _create_snapshot(id, description):
for i in range(1, 3):
try:
return ec2.create_snapshot(VolumeId=id, Description=description)
except ClientError as e:
print str(e)
time.sleep(1)
raise Exception('cannot create snapshot ' + description)
def _delete_snapshot(id):
for i in range(1, 3):
try:
return ec2.delete_snapshot(SnapshotId=id)
except ClientError as e:
print str(e)
time.sleep(1)
raise Exception('cannot delete snapshot ' + id)
1.テストを実施します。
1-1.「テストイベントの設定」を選択します。

1-2.テストイベントを設定します。

1-3.「イベントテンプレート」リストから [ Schedule Event ] を選択します。

1-4.イベント名を入力して【 作成 】をクリックします。

※コードはそのまま
1-5. 作成したイベントを選択してテスト をクリックします。

※『 実行結果 』が【 成功 】と表示される事を確認します。
2.スナップショットの確認します。
2-1.スナップショットが作成されている事が確認できます。

2-2.世代管理の確認します。
テストを複数回実行し、タグ「Backup-Generation」で設定した値のみ最新のスナップショットが保存されている事が確認できます。
CloudWatchでアラームを設定する事で、スナップショットの作成に失敗した場合にメールを送信することができます。