使用多个S3帐户运行EMR Spark

jsp*_*ner 10 amazon-s3 amazon-emr apache-spark

我有一个EMR Spark Job需要在一个帐户上从S3读取数据并写入另一个帐户.
我把工作分成两步.

  1. 从S3读取数据(因为我的EMR集群在同一帐户中,所以不需要凭据).

  2. 读取步骤1创建的本地HDFS中的数据,并将其写入另一个帐户的S3存储桶.

我试过设置hadoopConfiguration:

sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "<your access key>")
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey","<your secretkey>")
Run Code Online (Sandbox Code Playgroud)

并导出群集上的密钥:

$ export AWS_SECRET_ACCESS_KEY=
$ export AWS_ACCESS_KEY_ID=
Run Code Online (Sandbox Code Playgroud)

我已经尝试了群集客户端模式以及spark-shell而没有运气.

他们每个都返回一个错误:

ERROR ApplicationMaster: User class threw exception: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: 
Access Denied
Run Code Online (Sandbox Code Playgroud)

Joh*_*ein 16

解决方案实际上非常简单.

首先,EMR集群有两个作用:

这些角色在以下内容中进行了解释:Amazon EMR的默认IAM角色

因此,在群集中启动的每个EC2实例都会分配EMR_EC2_DefaultRole角色,从而通过Instance Metadata Service提供临时凭证.(有关其工作原理的说明,请参阅:Amazon EC2的IAM角色.)Amazon EMR节点使用这些凭据访问AWS服务,如S3,SNS,SQS,CloudWatch和DynamoDB.

其次,您需要向其他帐户中的Amazon S3存储桶添加权限,以允许通过该EMR_EC2_DefaultRole角色进行访问.这可以通过向S3存储桶(此处命名)添加存储桶策略来完成,other-account-bucket如下所示:

{
    "Id": "Policy1",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1",
            "Action": "s3:*",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::other-account-bucket",
                "arn:aws:s3:::other-account-bucket/*"
            ],
            "Principal": {
                "AWS": [
                    "arn:aws:iam::ACCOUNT-NUMBER:role/EMR_EC2_DefaultRole"
                ]
            }
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

此策略将所有S3权限(s3:*)授予EMR_EC2_DefaultRole属于ACCOUNT-NUMBER与策略中匹配的帐户的角色,该帐户应该是启动EMR群集的帐户.授予此类权限时要小心 - 您可能只想授予权限,GetObject而不是授予所有S3权限.

就这样!另一个帐户中的存储桶现在将接受来自EMR节点的请求,因为它们正在使用该EMR_EC2_DefaultRole角色.

免责声明:我通过在Account-A中创建一个存储桶并为Account-B中的角色分配权限(如上所示)来测试上述内容.在具有该角色的Account-B中启动了EC2实例.我能够通过AWS命令行界面(CLI)从EC2实例访问存储桶.我并没有内EMR测试它,但它应该工作方式相同.

  • 除了 `s3:GetObject` 权限之外,您可能还需要授予您想要使用的存储桶的 `s3:ListBucket` 权限。(如果您的存储桶经过 KMS 加密,请不要忘记 KMS 权限)。 (2认同)