ccl*_*eve 11 postgresql amazon-s3 amazon-web-services amazon-rds
我很难将数据从 S3 导入 RDS postgres 实例。根据 docs,您可以使用以下语法:
aws_s3.table_import_from_s3 (
table_name text,
column_list text,
options text,
bucket text,
file_path text,
region text,
access_key text,
secret_key text,
session_token text
)
Run Code Online (Sandbox Code Playgroud)
所以,在 pgAdmin 中,我这样做了:
SELECT aws_s3.table_import_from_s3(
'contacts_1',
'firstname,lastname,imported',
'(format csv)',
'com.foo.mybucket',
'mydir/subdir/myfile.csv',
'us-east-2',
'AKIAYYXUMxxxxxxxxxxx',
'3zB4S5jb1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
);
Run Code Online (Sandbox Code Playgroud)
我还对最后一个参数使用显式 NULL 进行了尝试。
我得到的错误信息是:
NOTICE: CURL error code: 51 when attempting to validate pre-signed URL, 1 attempt(s) remaining
NOTICE: CURL error code: 51 when attempting to validate pre-signed URL, 0 attempt(s) remaining
ERROR: Unable to generate pre-signed url, look at engine log for details.
SQL state: XX000
Run Code Online (Sandbox Code Playgroud)
我检查了服务器日志,没有进一步的信息。
我已经三重检查了所有参数的正确性。我如何使这项工作?
更新:
我可以确认我可以使用这些相同的凭据在 Java aws sdk 中执行 s3.getObject()。
小智 13
这里的主要问题是您需要 1) 向 RDS 实例添加一个 IAM 角色以访问 S3 存储桶,以及 2) 向运行 RDS 实例的 VPC 添加一个 S3 端点以允许通信。
这是我为使其工作而遵循的过程,在 shell 中使用 AWS cli 命令(正确处理所涉及的环境变量的值),希望它可以帮助:
$ aws iam create-role \
--role-name $ROLE_NAME \
--assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "rds.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
Run Code Online (Sandbox Code Playgroud)
$ aws iam create-policy \
--policy-name $POLICY_NAME \
--policy-document '{"Version": "2012-10-17", "Statement": [{"Sid": "s3import", "Action": ["s3:GetObject", "s3:ListBucket"], "Effect": "Allow", "Resource": ["arn:aws:s3:::${BUCKET_NAME}", "arn:aws:s3:::${BUCKET_NAME}/*"]}]}'
Run Code Online (Sandbox Code Playgroud)
$ aws iam attach-role-policy \
--policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/$POLICY_NAME \
--role-name $ROLE_NAME
Run Code Online (Sandbox Code Playgroud)
$ aws rds add-role-to-db-instance \
--db-instance-identifier $RDS_INSTANCE_NAME \
--feature-name s3Import \
--role-arn arn:aws:iam::$AWS_ACCOUNT_ID:role/$ROLE_NAME \
--region $REGION
Run Code Online (Sandbox Code Playgroud)
$ aws ec2 create-vpc-endpoint \
--vpc-id $VPC_ID \
--service-name com.amazonaws.$REGION.s3
--route-table-ids $ROUTE_TABLE_ID
Run Code Online (Sandbox Code Playgroud)
可以通过命令获取与创建端点的VPC相关的路由表id
$ aws ec2 describe-route-tables | jq -r '.RouteTables[] | "\(.VpcId) \(.RouteTableId)"'
Run Code Online (Sandbox Code Playgroud)
目前 (2020-10-16) 至少在 RDS Postgres 12.4 中,如果文件不在 S3 存储桶的根目录中,则从 S3 导入文件不起作用。
导入文件myfile.csv有效,导入文件mydir/subdir/myfile.csv无效。如果权限和其他一切正常,后者将给出这些类型的错误:
[XX000] ERROR: HTTP 403. Permission denied. Check bucket or provided credentials as they may no longer be valid.
Run Code Online (Sandbox Code Playgroud)
这是 AWS 的已知问题,据 AWS Support 称,他们正在解决这个问题。
此外,您似乎需要在添加文档中描述的角色后重新启动 RDS 实例。否则角色没有任何效果。文档中没有提到重启的需要。
一般来说,RDS s3Import 会给出非常混乱的错误消息。例如,导入长度为 0 的文件,会出现以下错误:
[Amazon](500310) Invalid operation: HTTP 416. Check your arguments and try again.;
Run Code Online (Sandbox Code Playgroud)
为了重现您的情况,我执行了以下操作:
AmazonRDSServiceRolePolicy了s3importSELECT aws_s3.table_import_from_s3()命令(如上)加载数据这对我来说效果很好。
鉴于您的错误消息与预签名 URL 相关,这表明您提供的凭据无权访问 S3 中的 CSV 文件。但是,您随后说您已成功使用这些凭据来检索该对象。因此,这不太可能是原因。
基于Reddit:使用 RDS s3Import 功能:aws 从 S3 导入 AWS RDS Postgres 11+ 时出现问题,该问题可能与Amazon RDS 实例无法访问 Amazon S3有关。这可能是因为它位于 VPC 中没有 NAT 网关的私有子网中。如果是这种情况,那么您可以添加 NAT 网关来提供 Internet 连接,或者如链接中所述,添加S3 的 VPC 终端节点。
该帖子中的另一条评论报告了同样的问题,安全组中缺少出站规则,导致 RDS 实例无法访问 Amazon S3。