迁移方案背景介绍
在 DynamoDB 迁移中,对于单表数据量超过上 100G 的情况,数据导出和导入需要几十分钟甚至几个小时,这对停机窗口时间要求较短的迁移场景带来了很大的挑战,因此需要一种可以缩短 DynamoDB 迁移时间的方案。本方案基于此而来,采用全量+CDC(增量)方式进行,适用于大表在线迁移需求。
迁移方案架构图
全量阶段: 通过 DynamoDB table Export 将数据导出到目标 S3 存储桶中。然后在目标账号通过 DynamoDB Import from S3 将数据导入到目标 DynamoDB。
CDC 阶段: 通过在源表中开启 Stream(类似 Kafka 流数据),当有数据变更时触发 Lambda 函数将数据写入到目标 DynamoDB。
本质上,全量阶段并不会缩短时间,通过结合 CDC,可以将 DynamoDB 的迁移提前进行。只要保证在正式迁移的时间窗口里 CDC 阶段能将目标端与源端的数据追平,然后再进行割接即可。
迁移操作步骤
基础配置
源账号 AWS IAM User 权限配置(临时迁移用途的 AWS IAM User)
由于仅为迁移目的进行一次性授权,为了减少配置过程,本文章部分权限授予“FullAccess”,实际项目可根据不同要求进行最小化权限配置。
用户授权开启源表 PITR 权限,所需权限如下:AmazonDynamoDBFullAccess、AWSCloudFormationFullAccess、AWSLambda_FullAccess、IAMRoleLimitedAccess、S3LimitedAccess。其中 IAMRoleLimitedAccess,S3LimitedAccess 为自定义策略,对应 policy 如下:
IAMRoleLimitedAccess
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:createRole",
"iam:AttachRolePolicy",
"iam:PutRolePolicy"
],
"Resource": "*"
}
]
}
S3LimitedAccess
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:ListBucket",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::your-target-account-s3-bucket/*",
"arn:aws:s3:::your-target-account-s3-bucket"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:CreateBucket",
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::aws-sam-cli-*/*",
"arn:aws:s3:::aws-sam-cli-*"
]
}
]
}
注:需要将上面 your-target-account-s3-bucket 替换真实的 s3 bucket。
开启源表 PITR 功能
使用被授权的源 IAM 用户为 DynamoDB 源表打开 PITR(下面的 demoTable 为示例表,正式配置需替换为真实的表名)
aws dynamodb update-continuous-backups \
--table-name demoTable \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true \
开启 DynamoDB 源表 Stream 功能
aws dynamodb update-table \
--table-name demoTable \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
如下图所示:
这里需要记住 LatestStreamARN 值,在 CDC 过程需要。
配置目标 S3 桶策略
需要在目标账号的 S3 Bucket 权限里面设置存储桶策略,具体权限如下:
{
"Version": "2012-10-17",
"Id": "Policy1605099029795",
"Statement": [
{
"Sid": "Stmt1605098975368",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<sourceaccountnumber>:user/<YourUser>"
},
"Action": [
"s3:ListBucket",
"s3:PutObjectAcl",
"s3:AbortMultipartUpload",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3::: <nameofyourbucket>",
"arn:aws:s3::: <nameofyourbucket>/*"
]
}
]
}
全量同步
在源账户中将 DynamoDB 导出到目标 S3
aws dynamodb export-table-to-point-in-time \
--table-arn <source DynamoDB table arn> \
--s3-bucket <target s3 bucket name> \
--s3-bucket-owner <target aws account id> \
在目标账户 DynameDB Console 界面通过 Import From S3 功能将数据从 S3 还原到目标 DynameDB:
注: Source S3 URL 一定要选择到对应的 data 目录。
在上图的页面设置 Table name、 Partition key,保持和源表相同的配置即可,然后进行 import 。
CDC 同步
目标账号授权源账号对 DynamoDB 可写权限
在添加 permissions 时选择创建新的 policy
在 json 输入框填录以下 policy 代码,需要将 target-region、target-account、target-dynamodb-name 替换为真实的信息。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:BatchGetItem",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:DescribeTable",
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": "arn:aws:dynamodb:<target-region>:<target-account>:table/<target-dynamodb-name>"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "dynamodb:ListTables",
"Resource": "*"
}
]
}
在源账户启动 SAM 代码进行 CDC
1. 安装基础软件
sudo yum install git
wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
sha256sum aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
sudo ./sam-installation/install
sam --version
sudo amazon-linux-extras install python3.8
2. 下载 SAM 代码并执行
git clone https://github.com/aws-samples/cross-account-amazon-dynamodb-replication.git
cd cross-account-amazon-dynamodb-replication/ChangeDataCapture
vim template.yml #(作如下修改,将 79 行 false 改为 true)
3. 执行 SAM 代码(请确定用户拥有 SAM 执行权限)
sam build
sam deploy –guided
CDC 参数说明:
TargetDynamoDBTable: Target DynamoDB Table name
TargetAccountNumber: Target AWS Account Number
TargetRoleName: Target IAM Role name to be assumed by Lambda function
TargetRegion: The region for the target DynamoDB table
MaximumRecordAgeInSeconds: The maximum age (in seconds) of a record in the stream that Lambda sends to your function.
SourceTableStreamARN: Source DynamoDB table stream ARN
以上成功执行后就会自动进行源表到目标表的 CDC。
参考资料
https://thinkwithwp.com/blogs/database/cross-account-replication-with-amazon-dynamodb/
https://github.com/aws-samples/cross-account-amazon-dynamodb-replication#initial-load
本篇作者