LoginSignup
9
9

More than 5 years have passed since last update.

LambdaでEC2インスタンスの日次スナップショットを取得する

Posted at

目的

EBSの日次スナップショットを取得し、7世代だけ保持するという要件が発生したため

構成

今回はカスタムメトリクス取得時と同様、以下のような構成にしました。
カスタムメトリクスをLambdaとCloudWatch Eventsを使って取得する

image

1.CloudWatch Eventsにて1日に1回スナップショット取得用Lambdaを呼び出す
2.LambdaにてEBSのスナップショットを取得する
3.取得した結果スナップショット数が上限値を超えたら一番古いスナップショットを削除する

IAMロールの設定

Lambda用にロールを作成し、以下ポリシーを紐づけます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1479031595000",
            "Effect": "Allow",
            "Action": [
                "ec2:CreateSnapshot",
                "ec2:CreateTags",
                "ec2:DeleteSnapshot",
                "ec2:DescribeSnapshots"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Lambdaの設定

設定

設定値は以下の通りです。

項目 設定値
Runtime Node.js 4.3
Handler index.handler
Role 作成したLambda用ロール
Memory 128 MB
Timeout 20 sec

コード

コードは以下の通りです。
※volumeIdを取得したいEBSのIDに変更してください。
※tagNameは取得したスナップショットのNameタグ名です。

'use strict';

const AWS = require('aws-sdk');
const ec2 = new AWS.EC2();

exports.handler = (event, context, callback) => {

    const generator  = (function *() {

        try {
            // スナップショットを取得する対象のEBSボリュームIDに変更します。
            const volumeId    = 'vol-xxxxxxxx';
            // 任意のタグ名
            const tagName     = 'xxxx-snapshot';
            // バックアップ保持世代数
            const retention   = 7;

            // スナップショットを作成
            const snapshotId = yield createSnapshot(volumeId, generator);

            // タグ付け
            yield createTags(snapshotId, tagName, generator);

            // スナップショットのリストを取得
            const snapshotsList = yield describeSnapshots(tagName, generator);

            // snapshotの数が保持世代数を超えたら削除
            if(snapshotsList.length > retention ) {
                yield deleteSnapshot(snapshotsList[snapshotsList.length-1].SnapshotId, generator);
            }

            callback(null, 'success');

        } catch (e) {
            callback(e.message);
        }
    })();

    /* 処理開始 */
    generator.next();

};

// スナップショットを作成
function createSnapshot(volumeId, generator) {

    const params = {
        VolumeId: volumeId
    };

    ec2.createSnapshot(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            generator.throw(new Error('create snapshot error : ' + params.VolumeId));
            return;
       }
       console.log('successful create snapshot : ' + params.VolumeId);
       generator.next(data.SnapshotId);
    });
}

// タグ付け
function createTags(snapshotId, tagName, generator) {

    const params = {
        Resources: [
            snapshotId
        ],
        Tags: [
            {
                Key  : "Name",
                Value: tagName
            }
        ]
    };

    ec2.createTags(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            generator.throw(new Error('create tags error : ' + params.Resources[0]));
            return;
       }
       console.log('successful create tags : ' + params.Resources[0]);
       generator.next();
    });
}

// スナップショットのリストを取得
function describeSnapshots(tagName, generator) {

    const params = {
        Filters: [
            {
                Name: 'tag-key',
                Values: [
                    'Name'
                ]
            },
            {
                Name: 'tag-value',
                Values: [
                    tagName
                ]
            }

        ]
    };

    ec2.describeSnapshots(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            generator.throw(new Error('describe snapshots error'));
            return;
       }
       console.log('successful describe snapshot');

       const snapshotsList = data.Snapshots;
       // 降順にならびかえ
       snapshotsList.sort(function(a,b){
           let createDateA = new Date(a.StartTime);
           let createDateB = new Date(b.StartTime);

           if(createDateA.getTime() > createDateB.getTime()) {
               return -1;
           }
           if(createDateA.getTime() < createDateB.getTime()) {
               return 1;
           }
           return 0;
       });
       generator.next(snapshotsList);
    });
}

// snapshotを削除する
function deleteSnapshot(snapshotId, generator) {

    const params = {
        SnapshotId: snapshotId
    };

    ec2.deleteSnapshot(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            generator.throw(new Error('delete snapshot error : ' + params.SnapshotId));
            return;
       }
       console.log('successful delete snapshot : ' + params.SnapshotId);
       generator.next();
    });
}

CloudWatch Eventsの設定

日次でLambdaを実行するためのイベントを作成します。

[CloudWatch] - [ルール] - [ルールの作成]から新しくルールを作成します。

スケジュール

毎日夜中の3時(日本時間)にsnapshotを取得したい場合は、Cron式を以下のようにします。

cron(0 18 * * ? *)

参考:ルールのスケジュール式の構文

ターゲット

ターゲットには作成したLambdaファンクションを指定してください。

以上の設定ができれば、CloudWatch Eventsの設定は完了です。

以上

動作確認をしたところ、毎日スナップショットが作成され、きっちり7世代だけ残ることが確認できました。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9