0
0

「RDSデータを長期的に格納」RDSからS3にスナップショットを自動的に輸出

Posted at

RDSでスナップショットが最大35日間保存できます。長期間保存するためには、S3にエクスポートする必要があります。ただし、これはAWSコンソールでの手動機能に制限されています。この記事では、自動エクスポート方法について説明します。

1.前提

事前に以下のサービスを用意しておきます。

  • Mysqlインスタントが立ち上がる(DBエンジンが任意)
  • S3バケットが立ち上がる(デフォルト設定)

本記事でrds-snapshot-archive-testというS3バケットを用意ました。

2.構築・流れ

Screenshot 2024-08-02 at 11.29.09.png

  1. RDS自体でスナップショットを撮影した時にSNSトピックにイベント送信
  2. SNSはラムダ処理にトリガー
  3. ラムダはRDSでS3輸出処理コマンドを実施(*)
  4. RDSはS3へスナップショット輸出処理を行う

KMS役割はスナップショットの暗号

S3へ輸出処理の時間は結構かかりますが、ラムダの処理ではなくRDSのです。そのため、ラムダ処理時間制限の懸念(15分以内)がありません。

3.SNSトピック設定

3.1 役割

RDSでスナップショットに関わるイベントがあれば、イベントをトピックに送信してS3をトリガーします。

3.2 手順

SNSに入って→新規トピック
SNS create.png

種類にスタンダードをしてトピック名を登録します。残り項目をデフォルトに設定したら大丈夫です。

4.権限設定

4.1 輸出ロールを作成

RDSでS3に輸出するため権限が必要です。ロールを作成して該当するS3権限をアサインします。

  1. IAMのロールに入る→新規ロールを登録
    Role.png
  2. 信頼ポリシーを選ぶ
    role 1.png

(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をポリシー追加

create role step 2.png

簡単にしたらAmazonS3FullAccessをつけても大丈夫ですが、実際では良くない方法です。
下に最小権限ポリシーを案内します。最小権限ポリシーを付けたら一旦こちらステップを飛ばしても大丈夫です。

4. レビュ-
create role step 3.png
ロール名を登録して一応完了します。

4.2 最小権限ポリシーを付け

上記のステップ2を飛ばしたらこちらで引き続きます。

  1. Inline policyを作成
    Screenshot 2024-08-02 at 12.18.09.png

  2. JSONを選ぶ
    Screenshot 2024-08-02 at 12.20.48.png

{
    "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

3. レビュー
Screenshot 2024-08-02 at 12.24.38.png
ポリシー名を登録します。

結果
Screenshot 2024-08-02 at 12.25.44.png

5.KMSキー設定

5.1 役割

Snapshotを暗号するためKMSキーが必要です。

5.2 手順

  1. KMSに入る->新規登録
    kms create.png

  2. ステップ1で以下のように設定
    kms step 1.png

  3. ラベルを自由に決める
    kms step 2.png

  4. キーユーザーを設定
    kms step 4.png
    上記の輸出ロールを指摘する。ちなにみ、ステップ3を飛ばしても大丈夫だ。

  5. 最後
    全て情報をチェックして登録します。

5.RDSでイベント登録

5.1 イベント登録

  1. RDSに入る→イベント登録→新規イベント登録作成

RDS SNS.png
2. イベント登録
Channel create.png

  • イベント登録名前を自由に入力
  • 送信先を上記のSNSトピックに設定
  • イベントカテゴリをCREATEに設定(ラムダトリガー数を減らすため)

結果
SNS createed.png

6.Lambda設定

6.1 新規ファンクション作成

  1. ラムダに入る→新規ファンクション作成
    lambda.png
  2. 以下のように設定します
    lambda2.png

6.2 トリガー元設定

SNSトピックにトリガー元を設定
lambda3.png
上記のSNSトピックARNを設定
lambda4.png

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画面を遷移

lambda 3.5.png

ラムダのロール詳細画面に遷移された!
Screenshot 2024-08-02 at 13.16.47.png

上記のインライポリシー設定のように以下のポリシーを追加してください。

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を用意してテスト

テンプレートに「SNS-notification」を選び
lambda create test.png

{
 "Records": [
   {
     "Sns": {
       "Message": " { \"Source ID\":\"test3\",\"Source ARN\":\"<貴方のsnapshot arn>", \"Event Message\":\"Manual snapshot created\"}"
     }
   }
 ]
}

7.2 RDSでスナップショットを撮って輸出過程を確認

スナップショットを作成

Screenshot 2024-08-03 at 16.47.57.png

Screenshot 2024-08-03 at 16.48.34.png

RDSのイベント

Screenshot 2024-08-03 at 16.58.36.png

スナップショットを撮るイベントが2件あってラムダをトリガーさせます。
Manual snapshot created
Creating manual snapshot

Creating manual snapshotはスナップショットが作成される段階で輸出できません。そのため、上記のラムダコードで以下の処理があります。

if(!isCreatedSnapshot(eventDetails["Event Message"]))
// 。。。。。
RDSからS3に輸出進捗を監視

RDSで「Export in AWSS3」に入って過程が監視できます
Screenshot 2024-08-03 at 16.59.43.png

S3でスナップショットを確認

Screenshot 2024-08-03 at 17.37.58.png

注意点

格納バケットのデータ量が早く増えるため、Life Cycleを適用した方がいいと思います。

8.その他

他の方法

AWSのEC2で以下のソースコードを実施してCloudFormationを作成して頂きます。CloudFormationを行うと必要なサービスが立ち上がります。

参考

最後まで読んで頂いて有り難うございます。
役に立つを感じしたらハートやコメントやを残ってください:bow:

0
0
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
0
0