Scala 无法将Spark SQL数据帧写入S3
我已经在EC2上安装了spark 2.0,我正在使用SparkSQL使用Scala从DB2检索记录,我想写入S3,在S3中我将访问密钥传递给spark上下文。下面是我的代码:Scala 无法将Spark SQL数据帧写入S3,scala,apache-spark,amazon-s3,apache-spark-sql,spark-dataframe,Scala,Apache Spark,Amazon S3,Apache Spark Sql,Spark Dataframe,我已经在EC2上安装了spark 2.0,我正在使用SparkSQL使用Scala从DB2检索记录,我想写入S3,在S3中我将访问密钥传递给spark上下文。下面是我的代码: val df = sqlContext.read.format("jdbc").options(Map( "url" -> , "user" -> usernmae, "password" -> password, "dbtable" -> tablename, "driver" -> "co
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时,这里发生的确切问题是什么??在AWS上创建EC2实例或EMR群集时,您可以选择在创建过程中将IAM角色附加到该实例或群集 默认情况下,不允许EC2实例连接到S3。您需要创建一个角色,并首先将其附加到实例 附加IAM角色的目的是授予IAM角色使用各种其他AWS服务的权限,而无需在该实例上安装物理凭据。鉴于存在拒绝访问错误,我假设该实例没有附加IAM角色,并且没有写入S3所需的足够权限 以下是创建新IAM角色的方法:
- 导航到AWS身份和访问管理(IAM)页面
- 单击角色,创建一个新角色
- 在搜索栏中搜索S3,然后选择S3FullAccess(…或者类似的东西,我记不得了)
- 添加您希望该角色拥有的任何其他服务
- 保存它
- 在实例创建步骤的页面中,选择VPC和子网,有一个IAM角色的选择框,单击该框并选择新创建的角色
- 继续并像以前一样创建实例。现在,该实例具有写入S3的权限。瞧李>
- 创建您的EMR集群,然后导航到GUI页面,在那里可以看到新集群的详细信息。找到右侧显示EMR角色的区域,然后在IAM区域中查找该角色,并通过添加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实现的,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")
查看此内容以了解s3、s3n和s3a之间的差异。您可以尝试此方法
df.write.mode("append").format("csv").save("path/to/s3/bucket");
从消息“拒绝访问”中可以看出,可能是用户在EMR上没有足够的pySpark权限,我得到
“SparkContext”对象没有属性“hadoopConfiguration”
,这是scala代码,最初的问题是scala,但它在pySpark中的概念非常相似。获取上下文对象,然后设置关键点。pyspark在这里似乎也有类似的讨论:对,我后来发现了差异。我使用的是pySpark,语法更像是sc.\u jdc.HadoopConfiguration().set()