无法将Spark SQL DataFrame写入S3

时间:2016-09-01 13:58:24

标签: scala apache-spark amazon-s3 apache-spark-sql spark-dataframe

我在EC2&上安装了spark 2.0我使用Scala来使用Scala从DB2&中检索记录。我想写入S3,我将访问密钥传递给Spark上下文。以下是我的代码:

val df = sqlContext.read.format("jdbc").options(Map( "url" -> , "user" -> usernmae, "password" -> password, "dbtable" -> tablename, "driver" -> "com.ibm.db2.jcc.DB2Driver")).option("query", "SELECT * from tablename limit 10").load()
df.write.save("s3n://data-analytics/spark-db2/data.csv")

它抛出以下异常:

org.apache.hadoop.fs.s3.S3Exception: org.jets3t.service.S3ServiceException: Service Error Message. -- ResponseCode: 403, ResponseStatus: Forbidden, XML Error Message: <?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>1E77C38FA2DB34DA</RequestId><HostId>V4O9sdlbHwfXNFtoQ+Y1XYiPvIL2nTs2PIye5JBqiskMW60yDhHhnBoCHPDxLnTPFuzyKGh1gvM=</HostId></Error>
Caused by: org.jets3t.service.S3ServiceException: Service Error Message.
  at org.jets3t.service.S3Service.putObject(S3Service.java:2358)
  at org.apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.storeEmptyFile(Jets3tNativeFileSystemStore.java:162)

这里发生的确切问题是什么,因为我也将访问密钥传递给Sparkcontext?写入S3的任何其他方式??

3 个答案:

答案 0 :(得分:2)

获得密钥后,这就是如何在s3n上的scala / spark2中写出s3。

spark.sparkContext.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "[access key]")
spark.sparkContext.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey", "[secret key]")
spark.sparkContext.hadoopConfiguration.set("fs.s3n.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")

df.write
.mode("overwrite")
.parquet("s3n://bucket/folder/parquet/myFile")

这是如何用s3a做的,这是首选。

spark.sparkContext.hadoopConfiguration.set("fs.s3a.access.key", "[access key]")
spark.sparkContext.hadoopConfiguration.set("fs.s3a.secret.key", "[secret key]")
spark.sparkContext.hadoopConfiguration.set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")

df.write
.mode("overwrite")
.parquet("s3a://bucket/folder/parquet/myFile")

请参阅此post以了解s3,s3n和s3a之间的差异。

答案 1 :(得分:0)

在AWS上创建EC2实例或EMR群集时,您可以在创建过程中选择将IAM角色附加到该实例或群集。

默认情况下,不允许EC2实例连接到S3。您需要创建一个角色,并首先将其附加到实例。

附加IAM角色的目的是可以为IAM角色授予使用各种其他AWS服务的权限,而无需在该实例上安装物理凭据。鉴于存在拒绝访问的错误,我假设该实例没有附加IAM角色,并且具有写入S3所需的足够权限。

以下是您如何创建新的IAM角色:

  • 导航至AWS身份和访问管理(IAM)页面。
  • 点击角色,创建一个新角色。
  • 在搜索栏中搜索S3,然后选择S3FullAccess(......或类似的东西,我无法记住它)
  • 添加您希望该角色拥有的任何其他服务。
  • 保存。

对于常规旧的单个EC2实例,请单击“创建新实例:

  • 并在实例创建步骤的页面中,您选择了VPC和子网,有一个IAM角色的选择框,单击该选择框并选择新创建的角色。
  • 继续并像以前一样创建您的实例。现在该实例具有写入S3的权限。瞧!

对于EMR群集:

  • 创建您的EMR群集,然后导航到GUI页面,您可以在其中看到新群集的详细信息。找到右侧显示 EMR Role 的区域,然后在您的IAM区域中找到该角色,并通过添加S3完整权限进行编辑。
  • 保存更改。

答案 2 :(得分:0)

你可以试试这个

df.write.mode("append").format("csv").save("path/to/s3/bucket");