[英]EMR Spark Fails to Save Dataframe to S3
我正在使用RunJobFlow
命令來啟動Spark EMR集群。 此命令將JobFlowRole
設置為IAM角色,該角色具有AmazonElasticMapReduceforEC2Role
和AmazonRedshiftReadOnlyAccess
策略。 第一個策略包含允許所有s3權限的操作。
當EC2實例啟動時,它們將承擔此IAM角色,並通過STS生成臨時憑證。
我做的第一件事是使用com.databricks.spark.redshift
格式從Redshift集群中讀取一個表到Spark Dataframe,並使用相同的IAM角色從JobFlowRole
卸載數據,就像我為EMR JobFlowRole
所做的JobFlowRole
。
據我所知,這會在Redshift上運行一個UNLOAD
命令轉儲到我指定的S3存儲桶中。 Spark然后將新卸載的數據加載到Dataframe中。 我使用推薦的s3n://
協議作為tempdir
選項。
此命令運行良好,它始終成功將數據加載到Dataframe中。
然后我運行一些轉換並嘗試將csv
格式的數據幀保存到相同的S3存儲桶Redshift Unloaded
into。
但是,當我嘗試這樣做時,它會拋出以下錯誤
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
並設置為via
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配置並通過s3n://ACCESS_KEY:SECRET_KEY@BUCKET/KEY
在s3 url中硬編碼了IAM用戶的憑據
當我運行它時,它吐出以下錯誤:
java.lang.IllegalArgumentException: Bucket name should be between 3 and 63 characters long
所以它試圖創建一個桶......這絕對不是我們想要它做的。
我真的很困惑這個,非常感謝這里的任何幫助! 我在本地運行時工作正常,但在EMR上完全失敗。
問題如下:
aws_iam_role
傳遞給了aws_iam_role
驅動程序。 然后,驅動程序為同一個IAM角色重新生成臨時憑證。 這使EC2實例生成的憑證無效。 它失敗了,因為它試圖使用過時的憑證。
解決方案是通過aws_iam_role
刪除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)
在亞馬遜EMR上,嘗試使用前綴s3://來引用S3中的對象。
這是一個很長的故事 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.