DynamoDBはテーブル全体または特定の期間のデータをS3へエクスポートする機能があります。
エクスポートしたデータはそのまま別テーブルとしてインポートをしたり、エクスポートしたデータをAthenaでクエリしたりできます。
エクスポートの目的が長期保存するアーカイブ用だったりデータ分析用だったりする場合、DynamoDBが稼働している本番環境とは別の開発用環境にエクスポートしたいと思う場面が多いのではないかと思います。
そこで今回は、DynamoDBテーブルを別アカウントのS3バケットへエクスポートする方法を紹介します。
方法
結論としては以下の公式ドキュメントに書いてある通りです。
ただ今回はAWSアカウントAAAAAAAAAAAAのDynamoDBからアカウントBBBBBBBBBBBBのS3へエクスポートする方法にフォーカスして紹介します。
基本的には以下を実施します。
- DynamoDBのポイントインタイムリカバリを有効にする
- エクスポート元(AAAAAAAAAAAA)でユーザーに対して権限を付与する
- エクスポート先(BBBBBBBBBBBB)でAAAAAAAAAAAAに対してバケットへアクセスを許可するバケットポリシーを付与する
- CLIやコードからエクスポートする場合は引数で bucket owner を指定する(← ここでハマりました)
- AWS CLI では
--s3-bucket-owner
- boto3 (Python) では
S3BucketOwner
- AWS CLI では
ポイントインタイムリカバリ(PITR)の有効化
DynamoDBにはポイントインタイムリカバリ(PITR)という仕組みがあります。
ここでは詳しくは説明しませんが、これが有効化されていることがS3エクスポートをする上で必須条件です。
Terraformの場合
resource "aws_dynamodb_table" "example" {
# 〜〜省略〜〜
point_in_time_recovery = "enabled"
}
参考: Resource: aws_dynamodb_table - Terraform Registry
CoudFormationの場合
---
Type: "AWS::DynamoDB::Table"
Properties:
# 〜〜省略〜〜
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
参考: AWS::DynamoDB::Table - AWS CloudFormation
エクスポート元で設定するIAMポリシー
エクスポートを実行する主体に対してIAMポリシーをアタッチします。コンソールから人がエクスポートするならばそのユーザーへ、LambdaからエクスポートするならばそのLambdaのIAMロールへ、というイメージです。
公式ドキュメントからコピペですが、以下のポリシーを付与すればよいです(DynamoDBテーブルやS3バケットのARNは適宜変えてください)。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowDynamoDBExportAction",
"Effect": "Allow",
"Action": "dynamodb:ExportTableToPointInTime",
"Resource": "arn:aws:dynamodb:us-east-1:111122223333:table/my-table"
},
{
"Sid": "AllowWriteToDestinationBucket",
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::your-bucket/*"
}
]
}
エクスポート先で設定するバケットポリシー
クロスアカウントでエクスポートする場合はS3バケットに対してエクスポート元からのアクセスを許可する必要があります。以下のポリシーをS3バケットに設定します(公式ドキュメントからのコピペです)。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStatement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/Dave"
},
"Action": [
"s3:AbortMultipartUpload",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::awsexamplebucket1/*"
}
]
}
上記は Dave
というユーザーに権限を与える例ですが、Lambdaなどロールを割り当てる場合はこれではできません。
Principal
にroleのARNを指定すればできそうなものですが、実はそうではないので注意です。なぜできないのかとどうすればできるかについては以下の記事にまとまっています。
特定ユーザーと特定のロールの両方を許可したい場合はこちらでできるそうです(試していません)。
ロールのID (ARNではなく) を調べる必要があったりと結構面倒なのでアカウント全体を許可する方が無難かもしれません(セキュリティ要件次第ですね)。その場合は root
を指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStatement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AAAAAAAAAAAA:root"
},
"Action": [
"s3:AbortMultipartUpload",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::dynamodb-export-bucket/*"
}
]
}
バケットオーナーの指定
ただのクロスアカウントアクセスだと思っていると気づかないのですが、DynamoDBのS3エクスポート時にはバケットオーナーを明示する必要があります。
AWS CLI の場合:
aws dynamodb export-table-to-point-in-time \
--table-arn arn:aws:dynamodb:ap-northeast-1:AAAAAAAAAAAA:table/TableName \
--s3-bucket dynamodb-export-bucket \
--s3-bucket-owner BBBBBBBBBBBB
2024年2月時点で最新のaws-cli 2.15.22で確認済みです。より正確な情報は最新のドキュメントでご確認ください。
参考: export-table-to-point-in-time - AWS CLI Command Reference
boto3の場合
dynamodb_client.export_table_to_point_in_time(
TableArn='arn:aws:dynamodb:ap-northeast-1:AAAAAAAAAAAA:table/TableName',
S3Bucket='dynamodb-export-bucket',
S3BucketOwner='BBBBBBBBBBBB'
)
2024年2月時点で最新のBoto3 1.34.47で確認済みです。より正確な情報は最新のドキュメントでご確認ください。
参考: export_table_to_point_in_time - Boto3 documentation
まとめ
DynamoDBから別アカウントへのS3バケットへエクスポートする方法をまとめました。特に最後の「バケットオーナーの指定」は見落としやすいポイントなのでご注意ください。