AWS

AWS EBSスナップショット自動化

AWS

EC2のタグ

Key Value
Name 任意の値 例) WP1
Backup-Generation スナップショット世代数 例) 5

スナップショットを行いたいEC2のインスタンスにタグを設定します。

 

Lambda

(@see https://qiita.com/HorieH/items/66bb68d12bd8fdbbd076#select-metric-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)

 

  • タイムアウト設定:Durationを20秒以上
    ※デフォルトは3秒、デフォルトだとエラーでこける場合があります。

 

 

Lambdaの実行ロールに下記のポリシーを設定する。

iam.json

{
    "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": [
                "*"
            ]
        }
    ]
}

 

 

CloudWatch Events

cronの役割を設定します。

 

 

CloudWatch Eventsでスケジュール

  • スケジュール:0 20 * * ? *
    ※”毎日、朝05時00分(JST)に実行する”という設定

※GMTとJSTの誤差は+9あるので、GMTに-9を行うとJSTで設定できる。GMTでしか設定できないのでこうするしかない。

世界標準時(経度0)より日本時間(経度135)は9時間速いと覚えておく。

 

 

Cloudwatchアラーム

  • Whenever:Errors
  • is: > 0
  • for: 1 consecutive periods
  • Period: 1 Day
  • Statistic: Sum

 

○Action

Send notificationに

  • topic name:任意の名前
  • Email list:メールアドレス

 

 

Lambdaをテスト実行して、世代管理されていたらOK!

 

 

@see https://qiita.com/HorieH/items/66bb68d12bd8fdbbd076#select-metric-1

Amazonおすすめ

iPad 9世代 2021年最新作

iPad 9世代出たから買い替え。安いぞ!🐱 初めてならiPad。Kindleを外で見るならiPad mini。ほとんどの人には通常のiPadをおすすめします><

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)