我正在尝试通过IntelliJ从笔记本电脑读取s3中的文件,以便我可以更轻松地开发我的Spark作业。
textFile RDD代码可在EMR集群内的Zeppelin中工作,但在本地尝试时不行。
在Zeppelin中,我不需要进行任何Spark上下文设置,大概是因为Zeppelin实例在AWS环境中,所以它对我来说就可以了。
我已经编写了用于创建临时AWS凭证的代码(使用IAM用户密钥),以便可以向Spark上下文提供会话令牌。访问密钥和秘密密钥也来自临时凭证。
val sqlContext = sparkSession.sqlContext
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.awsAccessKeyId", accessKeyId)
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.access.key", accessKeyId)
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.awsSecretAccessKey", secretAccessKey)
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.secret.key", secretAccessKey)
sqlContext.sparkContext.hadoopConfiguration
.set("fs.s3a.session.token", sessionToken)
sqlContext.sparkContext.hadoopConfiguration.set("fs.s3a.credentialsType", "AssumeRole")
sqlContext.sparkContext.hadoopConfiguration
.set(
"fs.s3a.stsAssumeRole.arn",
"arn:aws:iam::1234:role/someRoleThatWasUsedInTheWorkingTempCredCode"
)
sqlContext.sparkContext.hadoopConfiguration.set(
"fs.s3a.aws.credentials.provider",
"org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider"
)
sqlContext.sparkContext.textFile(
"s3a://path/to/file/that/definitely/exists/3714bb50a146.gz"
).collect()
我原本期望一个包含文件中数据的数组,但我却拒绝了权限。
org.apache.hadoop.security.AccessControlException: Permission denied: s3n://path/to/file/that/definitely/exists/3714bb50a146.gz
at org.apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.processException(Jets3tNativeFileSystemStore.java:449)
at org.apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.processException(Jets3tNativeFileSystemStore.java:427)
两个问题:
1)我正在做什么(执行从本地s3读取的spark作业)?
2)如果我正在做的事情可行,那么我的Spark上下文设置代码是否有效?我觉得我缺少属性或使用了错误的属性密钥。
答案 0 :(得分:1)
摆脱掉关于fs.s3a.impl的那一行。它所做的只是将默认映射从“ s3a”更改为“现代的,受支持的,维护的S3A连接器”,将其更改为“旧的,过时的,不受支持的S3N连接器”
您不需要该行。人们编写Spark应用程序总是这样做,这只是迷信。 Hadoop常见者知道哪个文件系统类处理s3a URL的方式与知道谁处理“文件”和“ hdfs”的方式相同