【问题标题】:Not able to write Spark SQL DataFrame to S3无法将 Spark SQL DataFrame 写入 S3
【发布时间】:2017-01-09 10:56:51
【问题描述】:

我已经在 EC2 上安装了 spark 2.0,我正在使用 SparkSQL,使用 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 吗??

【问题讨论】:

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


【解决方案1】:

拿到钥匙后,这是在 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 之间的区别。

【讨论】:

  • 在 EMR 上使用 pySpark,我得到 'SparkContext' object has no attribute 'hadoopConfiguration'
  • 这是 scala 代码,最初的问题是 scala,但它在 pyspark 中的概念非常相似。您获取上下文对象,然后设置键。似乎在这里对 pyspark 进行了类似的讨论:stackoverflow.com/questions/32155617/…
  • 对,后来我发现了不同。我用的是pySpark,语法更像sc._jdc.HadoopConfiguration().set()
【解决方案2】:

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

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

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

创建新 IAM 角色的方法如下:

  • 导航到 AWS Identity and Access Management (IAM) 页面。
  • 点击角色,创建一个新角色。
  • 在搜索栏中搜索 S3,然后选择 S3FullAccess(... 或类似的东西,我想不起来了)
  • 添加您希望该角色拥有的任何其他服务。
  • 保存。

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

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

对于 EMR 集群:

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

【讨论】:

    【解决方案3】:

    你可以试试这个

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 2019-01-16
      • 2020-06-12
      相关资源
      最近更新 更多