【问题标题】:Import Postgres data into RDS using S3 and aws_s3使用 S3 和 aws_s3 将 Postgres 数据导入 RDS
【发布时间】:2019-10-29 22:02:28
【问题描述】:

我很难将数据从 S3 导入 RDS postgres 实例。 According to the 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 
) 

所以,在 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()。

【问题讨论】:

  • 这可能是存储桶名称中的句点 (.)。这个问题现在有点老了,但值得从另一个名称中没有句点的存储桶尝试。几周前我遇到了这个。

标签: postgresql amazon-web-services amazon-s3 amazon-rds


【解决方案1】:

这里的主要问题是您需要 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)"'

【讨论】:

  • 天啊。非常感谢您发布此答案。
【解决方案2】:

目前(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,他们正在解决这个问题。

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

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

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

【讨论】:

  • 我遇到了完全相同的问题。当我将文件移动到存储桶的根目录时它起作用了。你说它是 AWS 的一个已知问题是什么意思?是否有工单、论坛、页面或任何表明他们正在研究解决方案的东西?
  • 升级到 Postgres 12.5 后问题已解决
  • 我就此联系了 AWS 支持,他们说这是一个已知错误。
【解决方案3】:

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

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

对我来说效果很好。

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

根据Reddit: Having issue with AWS RDS Postgres 11+ import from S3 using RDS s3Import feature : aws,该问题可能与Amazon RDS 实例无法访问Amazon S3这一事实有关。这可能是因为它位于 VPC 中没有 NAT 网关的 私有子网 中。如果是这种情况,那么您可以添加一个 NAT 网关来提供 Internet 连接,或者如链接中所述,添加一个 S3 的 VPC 端点

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

【讨论】:

  • 你已经超越了这里的职责范围。谢谢你。我的 RDS 实例确实有一个 Internet 网关,因为我可以从我的笔记本电脑上的 Postgres 端口访问它。正如我所提到的,我的 S3 存储桶也可以从公共互联网访问。我的 RDS 实例位于安全组中,其出站规则为 0.0.0.0/0 上的“所有流量”。其他想法?
  • 也许您可以尝试启动一个新的临时 RDS 实例,然后按照上述步骤查看它是否有效。然后,尝试找出与现有系统的差异。
  • @ccleve 你能解决吗?我也面临同样的问题。
  • @AakashBasu 不,我没有解决它。放弃。生命太短暂,无法处理 AWS 配置问题。我选择使用 INSERT 而不是 COPY。当您在单个语句中插入大量记录时,性能还不错。
  • 我正在尝试使用 Python Dataframe 来实现这一点,您能否建议如何实现它以获得更快的解决方案? psycopg2 库的性能不足以处理更大的数据。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

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

    我希望它有所帮助。

    【讨论】:

    • 我在管理 IAM 角色中看不到 rds-import-role。另外,我的出站规则是 All Traffic/All/All/0.0.0.0/0。对吗?
    • 入站不应允许所有流量到您的 RDS,而只允许您的服务 IP 白名单。出站,无论您从 RDS 发出什么请求,通常 RDS 或任何数据库都没有业务发送请求。但是这个 aws_s3 插件需要发送一个请求。 rds_import_role 您必须在 IAM 中自己创建。请点击此链接创建它,并且不要忘记为该 rds_import_roe docs.aws.amazon.com/AmazonRDS/latest/UserGuide/… 为您的 S3 存储桶分配策略访问权限
    【解决方案6】:

    我遇到了同样的问题。

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

    该问题与错误有关:

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

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

    【讨论】:

      【解决方案7】:

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

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

      【讨论】:

        猜你喜欢
        • 2021-02-06
        • 2022-10-14
        • 2021-01-11
        • 1970-01-01
        • 2020-02-11
        • 2018-06-19
        • 2020-06-21
        • 2020-05-11
        • 2015-05-21
        相关资源
        最近更新 更多