RDSのスナップショットをS3に定期的に保存する
RDSのsnapshotを定期的にS3に保存する必要があったので備忘録
およそ下図のようなことがしたい
1. 古いsnapshotを作成 & 新しいsnapshotを作成し、完成まで待機するlambdaの作成
snapshotの削除・作成は他サイトを参考にしつつ、snapshotが完成したらS3に保存したかったので check_snapshot_createdを追加した。[スナップショットに付けたいprefix名]などは適宜変更する。
iimport json import boto3 import time from botocore.client import ClientError from datetime import datetime, timedelta, tzinfo import threading rds = boto3.client('rds') s3 = boto3.resource('s3') class JST(tzinfo): def utcoffset(self, dt): return timedelta(hours=9) def dst(self, dt): return timedelta(0) def tzname(self, dt): return 'JST' def delete_snapshots(prefix, instanceid, days): snapshots = rds.describe_db_snapshots(DBInstanceIdentifier=instanceid) now = datetime.utcnow().replace(tzinfo=None) for snapshot in snapshots['DBSnapshots']: if 'SnapshotCreateTime'not in snapshot: continue delta = now - snapshot['SnapshotCreateTime'].replace(tzinfo=None) if snapshot['DBSnapshotIdentifier'].startswith(prefix) and delta.days >= days: rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot['DBSnapshotIdentifier']) def create_snapshot(prefix, instanceid): newsnapshotid = "-".join([prefix, datetime.now().strftime("%Y-%m-%d-%H-%M")]) rds.create_db_snapshot( DBSnapshotIdentifier=newsnapshotid, DBInstanceIdentifier=instanceid ) def check_snapshot_created(prefix, instanceid): snapshots = rds.describe_db_snapshots(DBInstanceIdentifier=instanceid)['DBSnapshots'] for snapshot in snapshots: if snapshot['Status'] != "available": time.sleep(20) check_snapshot_created(prefix, instanceid) def lambda_handler(event, context): snapshot_prefix = [スナップショットに付けたいprefix名] instance = [DBのインスタンス名] delete_days = 50 create_snapshot(snapshot_prefix, instance) delete_snapshots(snapshot_prefix, instance, delete_days) check_snapshot_created(snapshot_prefix, instance)
今回のlambdaはスナップショットが完成してないと20秒sleepする。 標準のlambdaのタイムアウトに一発で引っかかるので、lambdaのタイムアウト時間は適宜延長する。
2. lambda発火イベントと完了イベント追加
発火イベントはCloudwatch eventsをcronで実施。日本だと9時間ズレなので時刻を設定するときは気を付ける。完了イベントはいったんここまで完了したらメールを送ってもらうようテストしたかったのでSNSのトピックへ投げるように設定した。
3. S3へスナップショット
boto3のstart_export_taskを利用。 ここで指定するIAMにはS3の操作の権限を付ける。 最新のスナップショットをエクスポートするために取得してきたスナップショット一覧からSnapshotCreateTimeでソートして一つだけエクスポートを実施する。
import json import boto3 import time from botocore.client import ClientError from datetime import datetime, timedelta, tzinfo rds = boto3.client('rds') s3 = boto3.resource('s3') client = boto3.client('kms') def export_snapshot(prefix, instanceid): snapshots = rds.describe_db_snapshots(DBInstanceIdentifier=instanceid,SnapshotType='manual')['DBSnapshots'] snapshots= sorted(snapshots , key=lambda x: x['SnapshotCreateTime'],reverse=True) snapshot = snapshots[0] newsnapshotid = "-".join([prefix, datetime.now().strftime("%Y-%m-%d-%H-%M")]) response = rds.start_export_task( ExportTaskIdentifier= newsnapshotid, SourceArn= snapshot['DBSnapshotArn'], S3BucketName=[S3のバケット名], IamRoleArn=[IAMロール] KmsKeyId=[KMSkey], S3Prefix=[S3に付けたいプレフィックス名], ) return(response) def lambda_handler(event, context): snapshot_prefix = [スナップショットのprefix名] instance = [RDSのインスタンス名] export_snapshot(snapshot_prefix, instance)
4. 発火イベントの設定
2で設定したSNSのトピックからの発火を設定して完了 これで今回は朝5時になったらRDSのスナップショットを作成し、 それをS3へエクスポートする仕組みを自動化できた。