Apache spark 使用多个S3帐户运行EMR Spark
我有一份EMR Spark工作,需要在一个帐户上从S3读取数据,然后写入另一个帐户。Apache spark 使用多个S3帐户运行EMR Spark,apache-spark,amazon-s3,amazon-emr,Apache Spark,Amazon S3,Amazon Emr,我有一份EMR Spark工作,需要在一个帐户上从S3读取数据,然后写入另一个帐户。 我把工作分成两个步骤 从S3读取数据(无需凭据,因为我的EMR群集位于同一帐户中) 读取由步骤1创建的本地HDF中的数据,并将其写入另一个帐户中的S3存储桶 我已尝试设置hadoop配置: sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "<your access key>") sc.hadoopConfiguration.set("fs.s3
我把工作分成两个步骤
sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "<your access key>")
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey","<your secretkey>")
"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>>"
我尝试了集群和客户端模式,以及spark shell模式,但运气不佳
它们中的每一个都返回一个错误:
ERROR ApplicationMaster: User class threw exception: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception:
Access Denied
我认为您需要将IAM角色分配给您的计算节点(您可能已经这样做了),然后通过“远程”帐户上的IAM授予跨帐户访问该角色的权限。有关详细信息,请参阅。解决方案实际上非常简单 首先,EMR集群有两个角色:
- 向EMR服务授予权限的服务角色(
),例如用于启动Amazon EC2实例EMR\u DefaultRole
- 附加到群集中启动的EC2实例的EC2角色(
),允许其访问AWS凭据(请参阅)EMR\u EC2\u DefaultRole
EMR\u EC2\u DefaultRole
角色,该角色通过实例元数据服务提供临时凭据。(有关如何工作的解释,请参见:)Amazon EMR节点使用这些凭据访问AWS服务,如S3、SNS、SQS、CloudWatch和DynamoDB
其次,您需要向其他帐户中的Amazon S3 bucket添加权限,以允许通过EMR\u EC2\u DefaultRole
角色进行访问。这可以通过向S3 bucket(此处命名为其他帐户bucket
)添加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"
]
}
}
]
}
此策略将所有S3权限(S3:
)授予属于与策略中的账号匹配的帐户的EMR\u EC2\u DefaultRole
角色,该帐户应为启动EMR群集的帐户。在授予此类权限时要小心——您可能只希望将权限授予GetObject
,而不是授予所有S3权限
就这些另一个帐户中的bucket现在将接受来自EMR节点的请求,因为它们正在使用EMR\u EC2\u DefaultRole
角色
免责声明:我通过在Account-a中创建一个bucket并将权限(如上所示)分配给Account-B中的一个角色来测试上述内容。在Account-B中使用该角色启动了一个EC2实例。我能够通过服务器从EC2实例访问bucket。我没有在EMR中测试它,但是它应该以同样的方式工作。使用spark,您也可以使用Ascape角色访问另一个帐户中的s3存储桶,但在另一个帐户中使用IAM角色。这使其他帐户所有者更容易管理为spark作业提供的权限。通过s3 bucket策略管理访问可能是一件痛苦的事情,因为访问权限被分配到多个位置,而不是全部包含在单个IAM角色中
以下是Hadoop配置的
sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "<your access key>")
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey","<your secretkey>")
"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>>"
我们使用databricks进行上述操作,但尚未尝试使用EMR。为了控制资源的访问,通常将IAM角色作为标准实践进行管理。假设在您希望访问其他帐户中的资源时使用角色。如果你或你的组织遵循同样的原则,那么你应该遵循。
这里的基本思想是使用凭证提供者,EMRFS通过凭证提供者访问S3存储桶中的对象。
您可以更进一步,为本博客中创建的JAR参数化ARN for STS和bucket。请小心,它看起来像fs.s3n.awsAccessKeyId
仅适用于通过s3n://bucket/file
访问的文件。这可能不是系统从S3读取数据的方式。请参阅:。您的语句“首先,从S3读取数据(由于我的EMR群集位于同一帐户中,因此不需要凭据)”不太准确。EMR集群确实需要凭据才能访问AmazonS3内容。凭据通过与群集节点关联的角色传入。它提供对您自己的S3存储桶的访问权限。除了S3:GetObject
权限外,您可能还需要对希望使用的存储桶授予S3:ListBucket
权限。(如果你的桶是KMS加密的,别忘了KMS权限)。伙计,你救了我