我有一个EMR Spark Job需要在一个帐户上从S3读取数据并写入另一个帐户 我把工作分成两步。
从S3读取数据(因为我的EMR群集位于同一帐户中,因此无需凭据)。
读取步骤1创建的本地HDFS中的数据,并将其写入另一个帐户的S3存储桶。
我尝试设置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
答案 0 :(得分:12)
解决方案实际上非常简单。
首先,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实例)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和参数化的存储桶。