更新了Redshift加载IAM Role的说明
一、背景
在使用DMS向Redshift Serverless复制数据的过程中,添加Redshift Serverless为Target Endpoint,然后按下测试按钮,此时后收到报错:
Role 'dms-access-for-endpoint' is not configured properly.
根据有关文档,配置完成这个IAM Role后,开始Redshift复制任务,又会遇到错误,在DMS生成的CloudWatch日志中,出现如下错误:
2023-10-31T15:12:44 [TARGET_LOAD ]E: RetCode: SQL_ERROR SqlState: XX000 NativeError: 30 Message: [Amazon][Amazon Redshift] (30) Error occurred while trying to execute a query: [SQLState XX000] ERROR: exception name : UnauthorizedException, error type : 135, message: The requested role arn:aws:iam::1xxxxxxx:role/dms-access-for-endpoint is not associated to cluster, should retry : 0 DETAIL: ----------------------------------------------- error: exception name : UnauthorizedException, error type : 135, message: The requested role arn:aws:iam::133129065110:role/dms-access-for-endpoint is not associated to cluster, should retry : 0 code: 30000 context: query: 409714[child_sequence:1] location: xen_aws_credentials_mgr.cpp:422 process: padbmaster [pid=1073955240] ----------------------------------------------- [1022500] (ar_odbc_stmt.c:5007)
如何让DMS能够正确的连接到Redshift Serverless?
二、网络环境、IAM和Redshift集群准备
1、DMS加载到Redshift原理
这里涉及一个相当炸裂的事情,DMS写入Redshift并非是靠JDBC方式通过SQL写入数据,而是通过将原始数据导出为CSV格式文件,保存在一个临时S3存储桶上。然后,DMS通过ODBC连接到Redshift,再使用IAM Role的方式从S3加载数据,完成向DMS的复制。复制完成后,临时存储桶清空。这个过程,在官网文档中有描述,在DMS执行Redshift任务的日志(通过CloudWatch Loggroup)也可以看到。
因此,整个配置和排错过程,也就是围绕这个数据加载流程进行。
2、DMS和Redshift的网络设计
VPC设计:
- 本VPC包括Public Subnet和Private Subnet
- 本VPC的Private Subnet的路由表包含
0.0.0.0/0
去往NAT Gateway的路由,可以正常访问外部网络 - 本VPC创建了S3 Gateway Endpoint,位于Private Subnet
- 创建一个名叫
dms-redshift
的安全组,入站规则允许myself的所有流量 All traffic
入站,允许去往0.0.0.0/0
出站
Redshift的网络设计:
- Redshift Serverless关闭了Public Access
- Redshift Serverless打开了Enhanced VPC Access
- Redshift Serverless创建时候选择了本VPC的私有子网,没有选择公有子网
- 绑定
dms-redshift
的安全组
Redshift Serverless的网络配置部分,在Workgroup设置中可以看到。如下截图。
DMS复制实例的网络设计:
- DMS的Subnet Group创建在Private Subnet私有子网,且与Redshift位于同一个Private Subnet
- DMS关闭了Public Access
- 绑定
dms-redshift
的安全组
在满足以上情况下,继续IAM配置。
3、DMS所需要的IAM Role和IAM Policy
请进入IAM,新建一个Role,取名为dms-access-for-endpoint
。请注意这里必须用这个名字,这个是DMS向Redshift复制时候的限制。可参考本文末尾的文档即可看到这个限制。
为本IAM Role加入如下策略,可使用Inline策略,也可以预先编辑一个策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:CreateNetworkInterface",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInternetGateways",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:DeleteNetworkInterface",
"ec2:ModifyNetworkInterfaceAttribute"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:ListBucket",
"s3:DeleteBucket",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersion",
"s3:GetBucketPolicy",
"s3:PutBucketPolicy",
"s3:GetBucketAcl",
"s3:PutBucketVersioning",
"s3:GetBucketVersioning",
"s3:PutLifecycleConfiguration",
"s3:GetLifecycleConfiguration",
"s3:DeleteBucketPolicy"
],
"Resource": "arn:aws:s3:::dms-*"
}
]
}
创建名为dms-access-for-endpoint
的IAM Role之后,为本角色设置Trust relationships
。如下截图。
策略如下。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "dms",
"Effect": "Allow",
"Principal": {
"Service": "dms.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "redshift",
"Effect": "Allow",
"Principal": {
"Service": "redshift.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "redshiftserverless",
"Effect": "Allow",
"Principal": {
"Service": "redshift-serverless.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
保存完成。
需要注意的是,创建DMS的Target Endpoint和DMS Task时候,都不会提示选择IAM Role。因此这个IAM Role是个前置条件。
4、为Redshift Serverless添加IAM Role
进入Redshift Serverless的Namespaces配置界面,找到其中的安全和加密Security and encryption
标签栏,点击进入。如下截图。
点击编辑按钮,确认上一步创建的IAM Role被绑定上。一个Redshift Serverless集群可以同时绑定多个IAM Role。绑定后,需要3-5分钟生效。生效后界面上显示为绿色的In-sync
字样。如下截图。
至此准备完成。
三、配置DMS任务
1、将Redshift Serverless填写到DMS Target Endpoint
如果希望将数据写入DMS的Dev库(Schema),那么在Endpoint配置位置按照如下截图填写。
2、测试DMS Target Endpoint连接
这样即可将数据写入DEV Schema中。
在按照以上方式配置了Redshift和DMS后,测试连接即可成功。
3、在Redshift Serverless上创建Schema和表结构
为了确保数据一致,在目标库上手工创建表结构,这样避免DMS自动识别表结构转换不准确,发生数据类型不一致的问题。
由于Redshift的结构是 数据库 -> Schema -> 表
的三级关系,因此前文步骤在DMS Target Endpoint的配置中,输入的数据库是Redshift默认的dev
。
如果源站是MySQL,例如数据库是demo1,因为MySQL没有Schema概念,因此对等到Redshift上,还需要在dev
库下新建Schema demo1
。使用如下语句创建。
create schema demo1;
然后就是在Redshift使用建表语句,正常创建table即可。
4、创建任务
启动一个新的DMS任务,DMS Task配置与普通非Serverless的数据库配置方式是一样的。
在处理目标库的表时候,当重启任务的时候,为了保持数据一致,一般可选择Truncate
清空现有表,但是保持表结构。如下截图。
这里展开讲解:如果选择第一个选项Do nothing
,那么重启任务后,目标库上的数据可能会出现重复条目。如果选择Drop tables on target
,那么目标库的表在重启任务时候会被删除,同时其数据库用户权限也会丢失。然后重启任务,由DMS自动创建表。此时,DMS会根据源表的Schema自行转换格式建表 —— 由此有相当概率转换不准确,造成字段类型不匹配。因此对于手工创建了目标表确保字段一致性的场景,目标库被Drop是很不利的。因此这就是为什么这里推荐选择Truncate
。
由于目标库是Redshift,属于OLAP数据库,因此批量加载性能更好。在创建DMS任务时候,要选中batch
批处理的选项,这样可优化加载性能。如下截图。
在选择要复制的源库上的表这一步,不要使用默认的通配符%
,因为这样会把源库的系统库例如mysql
等都复制过来,造成大量错误。这里需要精确的输入源库上要复制的库和表的名字。例如输入demo1
数据库下cdcdata
表。如下截图。
创建任务完毕。
5、启动任务
如果之前配置有错误,那么可以选择Restart
重启,主要不要选择恢复Resume
,要选择Restart
重启。
当任务启动成功后,即可在Redshift Serverless的名为Dev的Schema下看到MySQL上的demo1
的数据库,其中的表正常被同步过来。
6、查看DMS日志
DMS的日志分成:
- Task:任务管理:
- Source Unload:从源库读取
- Target Load:目标库写入
等几个步骤。分步骤查看,即可看到错误是来自哪里。从DMS的任务控制台界面,即可跳转到CloudWatch的Loggroups界面。如下截图。
至此DMS复制到Redshift Serverless运行正常。
四、参考文档
Using AWS DMS with Amazon Redshift Serverless as a Target
How can I troubleshoot connectivity failures and errors for an AWS DMS task that uses Amazon Redshift as the target endpoint?
https://repost.aws/knowledge-center/dms-redshift-connectivity-failures
The migration task failed with the error role/dms-access-for-endpoint is not associated to cluster
https://stackoverflow.com/questions/77116459/dms-task-to-migrate-from-aurora-postgresql-to-redshift