我用的是 RunJobFlow
命令启动一个spark emr集群。此命令设置 JobFlowRole
一个有政策的iam角色 AmazonElasticMapReduceforEC2Role
以及 AmazonRedshiftReadOnlyAccess
. 第一个策略包含允许所有s3权限的操作。
当ec2示例启动时,它们承担这个iam角色,并通过sts生成临时凭证。
我要做的第一件事是使用 com.databricks.spark.redshift
格式化并使用相同的iam角色从redshift卸载数据,就像我对emr所做的那样 JobFlowRole
.
据我所知,这是一个 UNLOAD
命令redshift到我指定的s3 bucket中。spark然后将新卸载的数据加载到Dataframe中。我使用推荐的 s3n://
协议 tempdir
选项。
这个命令非常有效,它总是成功地将数据加载到Dataframe中。
然后我运行一些转换并尝试将Dataframe保存在 csv
格式化为相同的s3 bucket红移 Unloaded
进入。
但是,当我尝试这样做时,它抛出以下错误 java.lang.IllegalArgumentException: AWS Access Key ID and Secret Access Key must be specified as the username or password (respectively) of a s3n URL, or by setting the fs.s3n.awsAccessKeyId or fs.s3n.awsSecretAccessKey properties (respectively)
可以。所以我不知道为什么会发生这种情况,但是我试图通过设置推荐的hadoop配置参数来解决这个问题。然后我用 DefaultAWSCredentialsProviderChain
加载 AWSAccessKeyID
以及 AWSSecretKey
并通过 spark.sparkContext.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", <CREDENTIALS_ACCESS_KEY>) spark.sparkContext.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey", <CREDENTIALS_SECRET_ACCESS_KEY>)
当我再次运行它时,它会抛出以下错误: java.io.IOException: com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records. (Service: Amazon S3; Status Code: 403; Error Code: InvalidAccessKeyId;
可以。所以那没用。然后我删除了hadoop配置的设置,并通过在s3url中硬编码了iam用户的凭证 s3n://ACCESS_KEY:SECRET_KEY@BUCKET/KEY
当我运行这个时,它会抛出以下错误: java.lang.IllegalArgumentException: Bucket name should be between 3 and 63 characters long
所以它试图制造一个桶。。这绝对不是我们想要它做的。
我真的被困在这一个,并将非常感谢任何帮助在这里!当我在本地运行它时,它工作正常,但在emr上完全失败。
2条答案
按热度按时间zujrkrfu1#
问题如下:
ec2示例在emr引导阶段生成临时凭证
当我询问红移时,我通过了考试
aws_iam_role
到数据块驱动程序。然后,驱动程序为同一iam角色重新生成临时凭据。这使ec2示例生成的凭据无效。然后,我尝试使用旧凭据(以及存储在示例元数据中的凭据)上载到s3
它失败了,因为它试图使用过期的凭据。
解决方案是通过
aws_iam_role
并替换为以下内容:val credentials = EC2MetadataUtils.getIAMSecurityCredentials ... .option("temporary_aws_access_key_id", credentials.get(IAM_ROLE).accessKeyId) .option("temporary_aws_secret_access_key", credentials.get(IAM_ROLE).secretAccessKey) .option("temporary_aws_session_token", credentials.get(IAM_ROLE).token)
qgelzfjb2#
在amazonemr上,尝试使用前缀s3://来引用s3中的对象。
说来话长。