繁体   English   中英

使用 S3 和 aws_s3 将 Postgres 数据导入 RDS

[英]Import Postgres data into RDS using S3 and aws_s3

我很难将数据从 S3 导入 RDS postgres 实例。 根据文档,您可以使用以下语法:

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 
) 

因此,在 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'
);

我还尝试使用明确的 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

我检查了服务器日志,没有进一步的信息。

我已经三重检查了所有参数的正确性。 我该如何进行这项工作?

更新:

我可以确认我可以使用这些相同的凭据在 Java aws sdk 中执行 s3.getObject()。

这里的主要问题是您需要 1) 将 IAM 角色添加到 RDS 实例以访问 S3 存储桶,2) 将 S3 终端节点添加到运行 RDS 实例的 VPC 以允许通信。

这是我遵循使其工作的过程,在 shell 中使用 AWS cli 命令(正确处理所涉及的环境变量的值),希望它可以提供帮助:

  1. 创建 IAM 角色:
$ 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"}]}'
  1. 创建将附加到 IAM 角色的 IAM 策略:
$ 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}/*"]}]}'
  1. 附上政策:
$ aws iam attach-role-policy \
    --policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/$POLICY_NAME \
    --role-name $ROLE_NAME
  1. 将角色添加到特定实例 - 需要为每个新实例重复此步骤:
$ 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
  1. 为 S3 服务创建 VPC 终端节点:
$ aws ec2 create-vpc-endpoint \
    --vpc-id $VPC_ID \
    --service-name com.amazonaws.$REGION.s3
    --route-table-ids $ROUTE_TABLE_ID

可以通过命令获取与创建端点的VPC相关的路由表id

$ aws ec2 describe-route-tables | jq -r '.RouteTables[] | "\(.VpcId) \(.RouteTableId)"'

目前(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.

这是 AWS 已知的问题,根据 AWS Support,他们正在解决这个问题。

此外,您似乎需要在添加文档中描述的角色后重新启动 RDS 实例。 否则角色没有任何作用。 文档中没有提到需要重新启动。

一般来说,RDS s3Import 会给出非常混乱的错误消息。 例如,导入长度为 0 的文件,会出现以下错误:

[Amazon](500310) Invalid operation: HTTP 416. Check your arguments and try again.;

为了重现您的情况,我执行了以下操作:

  • 公有子网中启动了 Amazon RDS PostgreSQL 实例
  • Manage IAM Roles下,我为s3import分配了AmazonRDSServiceRolePolicy
  • 创建了一个表
  • 将 CSV 文件放入 S3
  • 使用SELECT aws_s3.table_import_from_s3()命令(如上)加载数据

它对我来说很好。

鉴于您的错误消息与预签名的 URL 相关,这表明您提供的凭据无权访问 S3 中的 CSV 文件。 但是,您随后说您已成功使用这些凭据检索 object。 因此,这不太可能是原因。

基于Reddit:使用 RDS s3Import 功能从 S3 导入 AWS RDS Postgres 11+ 时遇到问题: aws ,该问题可能与Amazon RDS 实例无法访问 Amazon S3的事实有关。 这可能是因为它位于 VPC 中没有 NAT 网关的私有子网中。 如果是这种情况,那么您可以添加一个 NAT 网关以提供 Internet 连接,或者如链接中所述,为 S3 添加一个 VPC 端点

该帖子中的另一条评论报告了安全组中缺少出站规则的相同问题,该规则阻止了 RDS 实例访问 Amazon S3。

检查您的 RDS 和 S3 是否在同一区域。 我遇到了同样的问题,并使用我的 Aurora RDS 同一区域中的存储桶修复了它。

在私有子网下部署生产集群时,我解决了同样的问题。

请检查您的集群安全组的出站(我的情况)

并且还将 rds-import-role 添加到“管理 IAM 角色”中,select 功能是 s3import

我希望它有所帮助。

我遇到过同样的问题。

ERROR:  Unable to generate pre-signed url, look at engine log for details

该问题与错误有关:

:LOG: S3 bucket names with a period (.) are not supported

就我而言,问题的根本原因是. (点)在存储桶的名称中。

假设您已正确配置所有内容,此问题的一个原因可能是网络 ACL。 确保有明确允许 DB 和 S3 之间连接的 NACL 规则。

在我们的案例中,我们使用terraform-aws-modules/vpc/aws模块进行 VPC 配置,它提供了广泛的 VPC 配置,包括 NACL。 在 AWS 控制台中手动检查生成的配置后,我们发现提供给模块的配置生成的规则过于严格。 这没有反映在任何错误消息中,因为从 RDS 到 S3 的请求只是在网络级别被阻止。

有类似的问题,私有子网中的 Postgres

使用 S3 的 VPC 端点解决了这个问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM