簡體   English   中英

EMR Spark無法將Dataframe保存到S3

[英]EMR Spark Fails to Save Dataframe to S3

我正在使用RunJobFlow命令來啟動Spark EMR集群。 此命令將JobFlowRole設置為IAM角色,該角色具有AmazonElasticMapReduceforEC2RoleAmazonRedshiftReadOnlyAccess策略。 第一個策略包含允許所有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加載AWSAccessKeyIDAWSSecretKey並設置為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上完全失敗。

問題如下:

  • EC2實例在EMR引導階段生成臨時憑證
  • 當我查詢Redshift時,我將aws_iam_role傳遞給了aws_iam_role驅動程序。 然后,驅動程序為同一個IAM角色重新生成臨時憑證。 這使EC2實例生成的憑證無效。
  • 然后我嘗試使用舊憑據(以及存儲在實例元數據中的憑據)上傳到S3

它失敗了,因為它試圖使用過時的憑證。

解決方案是通過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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM