LoginSignup
3
1

More than 1 year has passed since last update.

【データ基盤構築/AWS】RDSのスナップショットをLambdaを使ってS3に定期的にエクスポートする仕組みを作る

Posted at

今回の課題

下記の記事を参考にしながら、EC2にてRDSを連携させたRailsのアプリを動かすことができたため、
今回は、AWS Lambdaを使用して、RDS内のデータのスナップショットをS3に定期的にエクスポートする機能を作る。

S3にエクスポートしたデータは、今後Snowflakeにしたいと考えている。

RDSスナップショットをS3にエクスポートする機能を実装していく

実装手順

1)S3にてバケットを作成

RDSのスナップショットをエクスポートするためのS3バケットを作成しておく。

2)RDSのスナップショットを作成

DBスナップショットの取得ページの、
DBインスタンスでスナップショットを取得したいRDS内のDBを指定し、
スナップショット名でDBスナップショットの識別子を指定しておく。

※DBスナップショットの識別子は、スナップショットを復元する時などに使用するもので、今回の記事では使用しない。

image.png

3)RDSスナップショットをS3にエクスポートするために必要なポリシー&ロールの作成

3)-1.ポリシーの作成

RDSがエクスポート先のS3にアクセスしてエクスポートできるようにするためのポリシーを作成しておく。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject*",
                "s3:GetObject*",
                "s3:DeleteObject*"
            ],
            "Resource": [
                "arn:aws:s3:::[エクスポート先のバケット名]",
                "arn:aws:s3:::[エクスポート先のバケット名]/*"
            ]
        }
    ]
}

3)-2.ロールの作成

ロールの作成画面にて、
信頼されたエンティティタイプをAWSのサービスに指定し、
ユースケースはRDS - Add Role to Databaseに指定して次へをクリック。

image.png

次のページで3)-1で作成したポリシーを選択して、ロールの作成を完了する。
image.png

3)-3.作成したロールの信頼関係を書き換える

ロールの編集画面に飛び、信頼関係の編集タブをクリックし、
信頼ポリシーを編集をクリックして下記に書き換える。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "export.rds.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

これで、RDSスナップショットをS3にエクスポートするための権限の準備が完了した。

4)KMSの作成

KMSのページのカスタマー管理型のキーを選択し、デフォルトの設定でKMSを作成する。
ここで作成したキーは、Lambdaを作成後に使用する。

5)Lambdaの作成

5)-1.関数の作成を行う

Lambdaのページから関数の作成をクリックして下記のページに飛び、
ランタイムはPython 3.9を選択し、
実行ロールは基本的なLambdaアクセス権限で新しいロールを作成を選択して関数の作成を実施する。
image.png

5)-2.ポリシーとロールを作成

5)-1で基本的なLambdaアクセス権限で新しいロールを作成を選択したので、
AWSLambdaBasicExecutionRole-********-****-****-****-************というポリシー名を所持した[関数名]role-********というロール名で、新しいロールが作成されている。

そこで、下記のポリシーを別途作成し、
上記のLambda作成時に同時に作成した[関数名]role-********というロールにアタッチする。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole",
                "rds:StartExportTask"
            ],
            "Resource": "*"
        }
    ]
}

5)-3.Lambdaコードを作成

RDSスナップショットをS3にエクスポートするためのコードを作成する。

import json
import boto3
from datetime import datetime

SOURCE_ARN="arn:aws:rds:ca-central-1:************:snapshot:rails-ec2-rds" # エクスポート対象とするRDSスナップショットのARN
S3_BUCKET_NAME="snowflake-data-practice" # 出力先のS3バケット名
IAM_ROLE_ARN="arn:aws:iam::************:role/RDSToS3_export" # S3にエクスポートする際に使用するロールのARN
KMS_KEY_ID="arn:aws:kms:ca:central-1:************:key/********-****-****-****-**********" # 作成したKMSキーのARN

client = boto3.client('rds')

def lambda_handler(event, context):

    export_task_identifier="mysnapshot" + datetime.now().strftime("%Y%m%d%H%M%S")

    response = client.start_export_task(
        ExportTaskIdentifier=export_task_identifier,
        SourceArn=SOURCE_ARN,
        S3BucketName=S3_BUCKET_NAME,
        IamRoleArn=IAM_ROLE_ARN,
        KmsKeyId=KMS_KEY_ID,
        )

6)KMSのキーユーザーにLambdaのロールを追加

5)-2で作成したLambdaのロールを、4)で作成したKMSのキーユーザーに追加する。

※Lambda実行時にAn error occurred (KMSKeyNotAccessibleFault)というエラーが発生するのを防ぐため

7)定期実行されるように設定する

ここまでで、Lambdaを実行することでRDSスナップショットがS3にエクスポートされる仕組みを実装することができた。
最後に、RDSスナップショットがS3に定期的にエクスポートされるように設定を行う。

まずは、5)で作成したLambdaの関数のページに進み、トリガーを追加をクリックする。
image.png

トリガーにEventBridge(CloudWatch Events)を選択して、
スケジュール式を選択すれば、指定した時間おきにRDSスナップショットがS3にエクスポートされるようになる。
image.png

参考記事

まとめ

以上のように進めることで、
RDSのスナップショットをLambdaを使ってS3に定期的にエクスポートする仕組みを構築することができた。

おまけ

LambdaのPythonコードを理解する

Lambdaで実行したPythonコードに、どういったことが書かれているかしっかり理解するために調べてみた。
特に下記の部分が理解不足だった。

client = boto3.client('rds')

def lambda_handler(event, context):

    export_task_identifier="mysnapshot" + datetime.now().strftime("%Y%m%d%H%M%S")

    response = client.start_export_task(
        ExportTaskIdentifier=export_task_identifier,
        SourceArn=SOURCE_ARN,
        S3BucketName=S3_BUCKET_NAME,
        IamRoleArn=IAM_ROLE_ARN,
        KmsKeyId=KMS_KEY_ID,
        )

1)RDSにアクセスできるようにする

client = boto3.client('rds')

2)S3にエクスポートされた際のファイル名を設定しておく

export_task_identifier="mysnapshot" + datetime.now().strftime("%Y%m%d%H%M%S")

この場合、mysnapshot[現在日時]と命名される。

3)Lambdaが実行されたときに呼び出すコードを設定しておく

Lambdaが実行されたときに、下記の関数が呼び出される。

def lambda_handler(event, context):

※参考:PythonのLambda関数ハンドラー

4)RDSスナップショットをS3にエクスポートするための設定を行う

start_export_task内で、エクスポート元やエクスポート先やエクスポート字のファイル名などを設定する。

response = client.start_export_task(
    ExportTaskIdentifier=export_task_identifier, # S3にエクスポート時のファイル名を指定
    SourceArn=SOURCE_ARN, # RDSスナップショットを指定
    S3BucketName=S3_BUCKET_NAME, # エクスポート先のS3バケット名を指定
    IamRoleArn=IAM_ROLE_ARN, # S3をエクスポートするために使用するロールを指定
    KmsKeyId=KMS_KEY_ID, # KMSキーを指定
    )
3
1
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
3
1