AWS LambdaによるRDSの自動削除スクリプト

はじめに

DI部のおおたきです。今回AWS Lambdaを使ってRDSの削除スクリプトを書いてみました。
pythonコードは初めて書いてみましたので、色々突っ込みどころがあるかもしれませんがご了承ください!
作成したLambdaはCloudWatchでruleを作成して決まった時間に実行するようにしました。

ロールを作成する

Lambdaを実行するにはロールが必要になりますので、最初にロールを作成します。
Management ConsoleのIAMからRolesから「Create new role」をクリックします。
「AWS Service Role」から「AWS Lambda」を選択します。
rds_delete_lambda01
次に「Attach Policy」で「AmazonRDSFullAccess」を選択しロールを作成します。
rds_delete_lambda02

Lambda関数を作成する

CloudWatchの設定

Management ConsoleのLambdaから「Create a Lambda function」をクリックします。
「Select blueprint」で「Blank Function」をクリックします。「Configure triggers」で「CloudWatch Event」をクリックします。
rds_delete_lambda03
今回は毎日22時に実行するようにcron形式で記載しました。(時間の指定はUTCなので気をつけてください)
rds_delete_lambda04

スクリプトの設定

次に「Configure function」でLambdaのコードを記載します。
以下、今回作成したスクリプトになります。

import boto3
import logging
import os
import datetime

logger = logging.getLogger()
logger.setLevel(logging.INFO)
client = boto3.client('rds')

def lambda_handler(event, context):
    instanceId = os.environ.get('INSTANCE_ID')
    if not instanceId:
        logger.error('undefiend instance id')
        return

    logger.info('instanceId:' + instanceId)
    snapshot_list = client.describe_db_snapshots(
        DBInstanceIdentifier=instanceId,
        SnapshotType='manual'
    )

    db_snapshots = sorted(snapshot_list['DBSnapshots'], \
                          key=lambda x:x['SnapshotCreateTime'], reverse=True)
    max_num = int(os.environ.get('MAX_SNAPSHOT_NUM'))

    if (is_exist_instance()):
        for num in range(max_num, len(snapshot_list['DBSnapshots']) + 1):
            snapshot_id = db_snapshots[num - 1]['DBSnapshotIdentifier']
            logger.info('START delete snapshot')
            delete_snapshot(snapshot_id)
            logger.info('END delete snapshot')
            
        logger.info('START delete instance')
        delete_instance()
        logger.info('END delete instance')
    else:
        logger.info('not found instance')
    return

def delete_snapshot(snapshot_id):
    logger.info('delete snapshot id:' + snapshot_id)
    client.delete_db_snapshot(
        DBSnapshotIdentifier=snapshot_id
    )

def delete_instance():
    d = datetime.datetime.today().strftime('%Y%m%d%H%M%S')
    snapshot_id = os.environ.get('INSTANCE_ID') + '-' + d + '-auto'
    logger.info('snapshot id:' + snapshot_id)
    logger.info('delete instance id:' + os.environ.get('INSTANCE_ID'))
    client.delete_db_instance(
        DBInstanceIdentifier=os.environ.get('INSTANCE_ID'),
        SkipFinalSnapshot=False,
        FinalDBSnapshotIdentifier=snapshot_id
    )

def is_exist_instance():
    db_instances = client.describe_db_instances();
    target_instance = filter(lambda x : x['DBInstanceIdentifier'] == os.environ.get('INSTANCE_ID'), db_instances['DBInstances'])
    return len(target_instance) > 0

コードの解説をします。最初に環境変数からinstance idを取得しています。削除対象はここで取得したinstance idのインスタンスになります。

instanceId = os.environ.get('INSTANCE_ID')

次にスナップショットの一覧を取得しています。今回作成した削除スクリプトはインスタンスを削除する前にスナップショットを作成します。そのためスナップショットが増え続けないよう古いスナップショットを削除するために一覧を取得します。

    snapshot_list = client.describe_db_snapshots(
        DBInstanceIdentifier=instanceId,
        SnapshotType='manual'
    )

取得したスナップショットの一覧に対してスナップショット作成日時の降順になるようにソートをしています。

    db_snapshots = sorted(snapshot_list['DBSnapshots'], \
                          key=lambda x:x['SnapshotCreateTime'], reverse=True)

インスタンスの存在確認メソッドを呼出し、存在していれば古いスナップショットを削除し、インスタンス削除メソッドを呼出します。

    if (is_exist_instance()):
        for num in range(max_num, len(snapshot_list['DBSnapshots']) + 1):
            snapshot_id = db_snapshots[num - 1]['DBSnapshotIdentifier']
            logger.info('START delete snapshot')
            delete_snapshot(snapshot_id)
            logger.info('END delete snapshot')
            
        logger.info('START delete instance')
        delete_instance()
        logger.info('END delete instance')
    else:
        logger.info('not found instance')

delete_instanceメソッド内ではインスタンスを削除する前にスナップショットを作成しています。スナップショットIDは「インスタンスID-作成日時-auto」という名前になるようにしています。

    d = datetime.datetime.today().strftime('%Y%m%d%H%M%S')
    snapshot_id = os.environ.get('INSTANCE_ID') + '-' + d + '-auto'

環境変数の設定

環境変数の設定をします。
今回使用する環境変数は以下の2つになります。

  • INSTANCE_ID:削除対象のインタンスID
  • MAX_SNAPSHOT_NUM:スナップショット最大保持数

rds_delete_lambda05

ロールの設定

最初に作成したロールを設定します。
「Role」から「Choose an existing role」を選択し、「Existing role」から作成したロールを選択します。
rds_delete_lambda06

まとめ

以上でRDSの自動削除スクリプトの完成です。これでCloudWatchで指定した時間になるとインタンスが起動していれば自動で削除されるようになります。
LambdaのTimeOutはデフォルトでは3秒と短いため、今回は1分にして実行をしました。
RDSは起動している時間で課金されますので、24時間使用しないテスト環境などでは停止させる仕組みは必ず必要かと思います。
今回作成したスクリプトが参考になれば幸いです。