AWS LambdaによるRDSの自動削除スクリプト
はじめに
DI部のおおたきです。今回AWS Lambdaを使ってRDSの削除スクリプトを書いてみました。 pythonコードは初めて書いてみましたので、色々突っ込みどころがあるかもしれませんがご了承ください! 作成したLambdaはCloudWatchでruleを作成して決まった時間に実行するようにしました。
ロールを作成する
Lambdaを実行するにはロールが必要になりますので、最初にロールを作成します。 Management ConsoleのIAMからRolesから「Create new role」をクリックします。 「AWS Service Role」から「AWS Lambda」を選択します。 次に「Attach Policy」で「AmazonRDSFullAccess」を選択しロールを作成します。
Lambda関数を作成する
CloudWatchの設定
Management ConsoleのLambdaから「Create a Lambda function」をクリックします。 「Select blueprint」で「Blank Function」をクリックします。「Configure triggers」で「CloudWatch Event」をクリックします。 今回は毎日22時に実行するようにcron形式で記載しました。(時間の指定はUTCなので気をつけてください)
スクリプトの設定
次に「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:スナップショット最大保持数
ロールの設定
最初に作成したロールを設定します。 「Role」から「Choose an existing role」を選択し、「Existing role」から作成したロールを選択します。
まとめ
以上でRDSの自動削除スクリプトの完成です。これでCloudWatchで指定した時間になるとインタンスが起動していれば自動で削除されるようになります。 LambdaのTimeOutはデフォルトでは3秒と短いため、今回は1分にして実行をしました。 RDSは起動している時間で課金されますので、24時間使用しないテスト環境などでは停止させる仕組みは必ず必要かと思います。 今回作成したスクリプトが参考になれば幸いです。