RDSでスナップショットが最大35日間保存できます。長期間保存するためには、S3にエクスポートする必要があります。ただし、これはAWSコンソールでの手動機能に制限されています。この記事では、自動エクスポート方法について説明します。
1.前提
事前に以下のサービスを用意しておきます。
- Mysqlインスタントが立ち上がる(DBエンジンが任意)
- S3バケットが立ち上がる(デフォルト設定)
本記事でrds-snapshot-archive-test
というS3バケットを用意ました。
2.構築・流れ
- RDS自体でスナップショットを撮影した時にSNSトピックにイベント送信
- SNSはラムダ処理にトリガー
- ラムダはRDSでS3輸出処理コマンドを実施(*)
- RDSはS3へスナップショット輸出処理を行う
KMS役割はスナップショットの暗号
S3へ輸出処理の時間は結構かかりますが、ラムダの処理ではなくRDSのです。そのため、ラムダ処理時間制限の懸念(15分以内)がありません。
3.SNSトピック設定
3.1 役割
RDSでスナップショットに関わるイベントがあれば、イベントをトピックに送信してS3をトリガーします。
3.2 手順
種類にスタンダードをしてトピック名を登録します。残り項目をデフォルトに設定したら大丈夫です。
4.権限設定
4.1 輸出ロールを作成
RDSでS3に輸出するため権限が必要です。ロールを作成して該当するS3権限をアサインします。
(2)所に以下のJSONを貼り付けてください。
意味:信頼されるexport.rds.amazonaws.com
側はこちらロールとしてS3に輸出できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "export.rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
3. ステップ2をポリシー追加
簡単にしたらAmazonS3FullAccess
をつけても大丈夫ですが、実際では良くない方法です。
下に最小権限ポリシーを案内します。最小権限ポリシーを付けたら一旦こちらステップを飛ばしても大丈夫です。
4.2 最小権限ポリシーを付け
上記のステップ2を飛ばしたらこちらで引き続きます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExportPolicyToCustomS3Bucket",
"Effect": "Allow",
"Action": [
"s3:PutObject*",
"s3:ListBucket",
"s3:GetObject*",
"s3:DeleteObject*",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::<輸出先S3バケット>",
"arn:aws:s3:::<輸出先S3バケット>/*"
]
}
]
}
本記事では私の<輸出先S3バケット>はrds-snapshot-archive-test
5.KMSキー設定
5.1 役割
Snapshotを暗号するためKMSキーが必要です。
5.2 手順
-
最後
全て情報をチェックして登録します。
5.RDSでイベント登録
5.1 イベント登録
- RDSに入る→イベント登録→新規イベント登録作成
- イベント登録名前を自由に入力
- 送信先を上記のSNSトピックに設定
- イベントカテゴリを
CREATE
に設定(ラムダトリガー数を減らすため)
6.Lambda設定
6.1 新規ファンクション作成
6.2 トリガー元設定
SNSトピックにトリガー元を設定
上記のSNSトピックARNを設定
6.3 処理コード
import { RDSClient, StartExportTaskCommand } from "@aws-sdk/client-rds";
const REGION = "ap-northeast-1";
const rdsClient = new RDSClient({ region: REGION });
const checkSnapshotType = (eventMsg) => {
if (eventMsg?.includes("automated") || eventMsg?.includes("Automated") ) return "AUTOMATED";
if (eventMsg?.includes("manual") || eventMsg?.includes("Manual") ) return "MANUAL";
return "UNKNOWN";
};
const isCreatedSnapshot = (eventMsg) => {
if (eventMsg?.includes("created")) return true;
return false;
};
const getCurrentTime =()=>{
const now = new Date();
return `${now.getUTCFullYear()}-${now.getUTCMonth()+1}-${now.getUTCDate()}-${now.getUTCHours()}-${now.getUTCMinutes()}-${now.getUTCSeconds()}`
}
export const handler = async (event) => {
try {
const snsEvent = event?.Records[0]?.Sns;
// CloudWatchでイベント詳細を閲覧
// Snapshot情報があります
console.log("[INFO]: EVENT_Records_SNS:", snsEvent);
const eventDetails = await JSON.parse(snsEvent.Message);
const snapshotType = checkSnapshotType(eventDetails["Event Message"]);
// snapshot種類次第で、輸出するかどうかsnapshotTypeで処理できます
const sourceID = eventDetails["Source ID"];
const sourceARN = eventDetails["Source ARN"];
const takenTime = eventDetails["Event Time"]?.slice(0,10);
// create とcreated との2つイベントにS3がトリガーされるが、
// しかし、createの時にsnapshotが作成中で輸出不可で、ラムダがこちらイベントを無視します
if(!isCreatedSnapshot(eventDetails["Event Message"])){
return {
statusCode: 400,
body: JSON.stringify("[ERROR]: Snapshot is creating, cannot export",sourceID),
}
}
// 命名が任意
const snapshotNameInS3 = `${snapshotType}-${getCurrentTime()}`
const targetBucket = "rds-snapshot-archive-test";
const roleArn = "arn:aws:iam::<貴方のAWSアカウントID>:role/Demo-RDS-Export-SS-S3";
const kmsKeyArn = "arn:aws:kms:ap-northeast-1:<貴方のAWSアカウントID>:key/3dfefad9-894f-496e-93d8-47771f34ecf0";
const params = {
ExportTaskIdentifier: snapshotNameInS3,
SourceArn: sourceARN,
S3BucketName: targetBucket,
IamRoleArn: roleArn,
KmsKeyId: kmsKeyArn,
};
const command = new StartExportTaskCommand(params);
const data = await rdsClient.send(command);
console.log(`[INFO] Export task started: ${JSON.stringify(data)}`);
const response = {
statusCode: 200,
body: JSON.stringify("Start export source ID",sourceID),
};
return response;
} catch (error) {
console.error(`[Error]: starting export task: ${error}`);
return {
statusCode: 500,
body: JSON.stringify("Error starting export task"),
};
}
};
注意点
-
targetBucket
が貴方の輸出S3バケット先 -
roleArn
が 貴方の輸出ロールのARN -
kmsKeyArn
が 貴方のKMSキーのARN
6.4 ポリシー追加
ラムダ上で「configuration」→「permission」→「role name」を押下→IAMRole画面を遷移
上記のインライポリシー設定のように以下のポリシーを追加してください。
1.AWSLambdaBasicExecutionRole-2786dd6c-98c1-4fc
こちらはCloudWatchのデフォルト権限で既存しています。
2. kms-access
KMSアクセス権
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:CreateGrant",
"kms:DescribeKey",
"kms:RetireGrant"
],
"Resource": "arn:aws:kms:ap-northeast-1:<貴方のAWSアカウントID>:key/3dfefad9-894f-496e-93d8-47771f34ecf0"
}
]
}
3. Access-RDS-Snapshot
snapshotアクセス権
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RDSPolicy",
"Effect": "Allow",
"Action": [
"rds:DescribeDBSnapshots",
"rds:DescribeExportTasks",
"rds:StartExportTask"
],
"Resource": [
"arn:aws:rds:ap-northeast-1:<貴方のAWSアカウントID>:snapshot:*"
]
}
]
}
4. Lambda pass role
とはラムダは輸出ロールを投げる権
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IamPassRoleForDemoS3TriggerRDS",
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "*"
}
]
}
7.テスト
7.1.ラムダテストJsonを用意してテスト
{
"Records": [
{
"Sns": {
"Message": " { \"Source ID\":\"test3\",\"Source ARN\":\"<貴方のsnapshot arn>", \"Event Message\":\"Manual snapshot created\"}"
}
}
]
}
7.2 RDSでスナップショットを撮って輸出過程を確認
スナップショットを作成
RDSのイベント
スナップショットを撮るイベントが2件あってラムダをトリガーさせます。
・Manual snapshot created
・Creating manual snapshot
Creating manual snapshot
はスナップショットが作成される段階で輸出できません。そのため、上記のラムダコードで以下の処理があります。
if(!isCreatedSnapshot(eventDetails["Event Message"]))
// 。。。。。
RDSからS3に輸出進捗を監視
RDSで「Export in AWSS3」に入って過程が監視できます
S3でスナップショットを確認
注意点
格納バケットのデータ量が早く増えるため、Life Cycleを適用した方がいいと思います。
8.その他
他の方法
AWSのEC2で以下のソースコードを実施してCloudFormationを作成して頂きます。CloudFormationを行うと必要なサービスが立ち上がります。
参考
最後まで読んで頂いて有り難うございます。
役に立つを感じしたらハートやコメントやを残ってください