使用多个S3帐户运行EMR Spark

时间:2016-11-01 16:40:22

标签: apache-spark amazon-s3 amazon-emr

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

  1. 从S3读取数据(因为我的EMR群集位于同一帐户中,因此无需凭据)。

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

  3. 我尝试设置hadoopConfiguration

    sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "<your access key>")
    sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey","<your secretkey>")
    

    导出群集上的密钥:

    $ export AWS_SECRET_ACCESS_KEY=
    $ export AWS_ACCESS_KEY_ID=
    

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

    每个人都会返回错误:

    ERROR ApplicationMaster: User class threw exception: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: 
    Access Denied
    

4 个答案:

答案 0 :(得分:12)

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

首先,EMR集群有两个角色:

  • 授予EMR服务权限的服务角色 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) return; switch (requestCode) { case PICK_FROM_CAMERA: /** * After taking a picture, do the crop */ doCrop(); break; case PICK_FROM_FILE: /** * After selecting image from files, save the selected path */ Toast.makeText(this,"in gall",Toast.LENGTH_LONG).show(); mImageCaptureUri = data.getData(); Log.e("URI", mImageCaptureUri.toString()); doCrop(); break; case crop: Log.e("URI2", mImageCaptureUri.toString()); Bundle extras = data.getExtras(); /** * After cropping the image, get the bitmap of the cropped image and * display it on imageview. */ if(extras!=null) { Bitmap photo = extras.getParcelable("data"); Log.e("URI9", mImageCaptureUri.toString()); mImageView.setImageBitmap(photo); } // File f = new File(mImageCaptureUri.getPath()); /** * Delete the temporary image */ // if (f.exists()) // f.delete(); break; } } )(例如,用于启动Amazon EC2实例)
  • 附加到群集中启动的EC2实例的 EC2角色EMR_DefaultRole),授予他们访问AWS凭据的权限(请参阅Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances

这些角色在Default IAM Roles for Amazon EMR

中有解释

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

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

other-account-bucket

此政策将所有S3权限({ "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" ] } } ] } )授予属于与策略中s3:*匹配的帐户的EMR_EC2_DefaultRole角色,该帐户应该是EMR群集中的帐户已启动,推出。授予此类权限时要小心 - 您可能只想授予ACCOUNT-NUMBER权限,而不是授予所有S3权限。

这就是全部!其他帐户中的存储区现在将接受来自EMR节点的请求,因为它们使用GetObject角色。

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

答案 1 :(得分:0)

我认为您需要为计算节点分配IAM角色(您可能已经这样做了),然后通过“远程”帐户上的IAM授予对该角色的跨帐户访问权限。有关详细信息,请参阅http://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html

答案 2 :(得分:0)

使用spark时,您还可以使用承担角色来访问另一个帐户中的s3存储桶,而在另一个帐户中使用IAM角色。这使其他帐户所有者可以更轻松地管理提供给Spark作业的权限。通过访问权限分配到多个位置而不是全部包含在单个IAM角色中,通过s3存储桶策略管理访问可能会很痛苦。

这里是hadoopConfiguration

"fs.s3a.credentialsType" -> "AssumeRole",
"fs.s3a.stsAssumeRole.arn" -> "arn:aws:iam::<<AWSAccount>>:role/<<crossaccount-role>>",
"fs.s3a.impl" -> "com.databricks.s3a.S3AFileSystem",
"spark.hadoop.fs.s3a.server-side-encryption-algorithm" -> "aws:kms",
"spark.hadoop.fs.s3a.server-side-encryption-kms-master-key-id" -> "arn:aws:kms:ap-southeast-2:<<AWSAccount>>:key/<<KMS Key ID>>"

外部ID也可以用作密码短语

"spark.hadoop.fs.s3a.stsAssumeRole.externalId" -> "GUID created by other account owner"

由于上述原因,我们正在使用数据块,但尚未尝试使用EMR。

答案 3 :(得分:0)

为控制资源的访问,通常将IAM角色作为标准做法进行管理。假设您要访问其他帐户中的资源时使用角色。如果您或您的组织遵循相同的规则,则应遵循https://aws.amazon.com/blogs/big-data/securely-analyze-data-from-another-aws-account-with-emrfs/。 此处的基本思想是使用凭据提供程序,EMRFS通过该凭据提供程序访问访问S3存储桶中的对象。 您可以再进一步一步,为在此博客中创建的JAR设置用于STS的ARN和参数化的存储桶。