Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如果我有身份验证详细信息,如何使用spark编程API写入HDFS?_Scala_Apache Spark_Hadoop_Authentication_Hdfs - Fatal编程技术网

Scala 如果我有身份验证详细信息,如何使用spark编程API写入HDFS?

Scala 如果我有身份验证详细信息,如何使用spark编程API写入HDFS?,scala,apache-spark,hadoop,authentication,hdfs,Scala,Apache Spark,Hadoop,Authentication,Hdfs,我需要写入外部HDFS集群,其身份验证详细信息可用于简单身份验证和kerberos身份验证。为了简单起见,假设我们正在处理简单的身份验证 这就是我所拥有的: 外部HDFS群集连接详细信息(主机、端口) 身份验证详细信息(用于简单身份验证的用户) 需要写入文件的HDFS位置(hdfs://host:port/loc) 还有其他细节,如格式等 请注意,SPARK用户与为HDFS身份验证指定的用户不同 现在,使用spark编程API,我正在尝试这样做: val hadoopConf = new

我需要写入外部HDFS集群,其身份验证详细信息可用于简单身份验证和kerberos身份验证。为了简单起见,假设我们正在处理简单的身份验证

这就是我所拥有的:

  • 外部HDFS群集连接详细信息(主机、端口)
  • 身份验证详细信息(用于简单身份验证的用户)
  • 需要写入文件的HDFS位置(hdfs://host:port/loc)
  • 还有其他细节,如格式等
请注意,SPARK用户与为HDFS身份验证指定的用户不同

现在,使用spark编程API,我正在尝试这样做:

val hadoopConf =  new Configuration()
hadoopConf.set("fs.defaultFS", fileSystemPath)
hadoopConf.set("hadoop.job.ugi", userName)
val jConf = new JobConf(hadoopConf)
jConf.setUser(user)
jConf.set("user.name", user)
jConf.setOutputKeyClass(classOf[NullWritable])
jConf.setOutputValueClass(classOf[Text])
jConf.setOutputFormat(classOf[TextOutputFormat[NullWritable, Text]])

outputDStream.foreachRDD(r => {
                val rdd = r.mapPartitions { iter =>
                    val text = new Text()
                    iter.map { x =>
                        text.set(x.toString)
                        println(x.toString)
                        (NullWritable.get(), text)
                    }
                }

                val rddCount = rdd.count()
                if(rddCount > 0) {
                    rdd.saveAsHadoopFile(config.outputPath, classOf[NullWritable], classOf[Text], classOf[TextOutputFormat[NullWritable, Text]], jConf)
                }
            })
在这里,我假设如果我们传递带有正确详细信息的JobConf,它应该用于身份验证,并且应该使用JobConf中指定的用户完成写入

但是,无论JobConf(“hdfs”作为用户)中存在的身份验证详细信息如何,写入仍然作为spark用户(“root”)进行。以下是我得到的例外情况:

Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Permission denied: user=root, access=WRITE, inode="/spark-deploy/out/_temporary/0":hdfs:supergroup:drwxr-xr-x
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.check(FSPermissionChecker.java:319)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.check(FSPermissionChecker.java:292)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkPermission(FSPermissionChecker.java:213)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkPermission(FSPermissionChecker.java:190)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:1698)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:1682)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkAncestorAccess(FSDirectory.java:1665)
at org.apache.hadoop.hdfs.server.namenode.FSDirMkdirOp.mkdirs(FSDirMkdirOp.java:71)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.mkdirs(FSNamesystem.java:3900)
at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.mkdirs(NameNodeRpcServer.java:978)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.mkdirs(ClientNamenodeProtocolServerSideTranslatorPB.java:622)
at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:969)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2049)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2045)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2043)

at org.apache.hadoop.ipc.Client.call(Client.java:1475)
at org.apache.hadoop.ipc.Client.call(Client.java:1412)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:229)
at com.sun.proxy.$Proxy40.mkdirs(Unknown Source)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.mkdirs(ClientNamenodeProtocolTranslatorPB.java:558)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:191)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
at com.sun.proxy.$Proxy41.mkdirs(Unknown Source)
at org.apache.hadoop.hdfs.DFSClient.primitiveMkdir(DFSClient.java:3000)
... 45 more

如果有任何建议,请告诉我。

这可能是一个评论,而不是一个答案,但因为太长,我把它放在这里。我没有尝试过这个,因为我没有环境来测试它。请尝试让我知道这是否有效(如果无效,我将删除此答案)

仔细查看一下代码,它看起来像是使用了
UserGroupInformation.getCurrentUser()
(我没有向下跟踪
createHAProxy
分支,但我怀疑那里有相同的逻辑)。然后将此信息发送到服务器进行身份验证

这意味着您需要更改在特定调用的上下文中返回的内容。这就是应该做的,所以您只需要获得一个适当的
UserGroupInformation
实例。在简单身份验证的情况下,实际上可能会起作用

因此,我建议尝试以下方式:

...
val rddCount = rdd.count()
if(rddCount > 0) {
    val remoteUgi = UserGroupInformation.createRemoteUser("hdfsUserName")
    remoteUgi.doAs(() => { rdd.saveAsHadoopFile(config.outputPath, classOf[NullWritable], classOf[Text], classOf[TextOutputFormat[NullWritable, Text]], jConf) })
}

root用户是运行spark submit的用户吗?你没有编辑SparkSession的jobConf,你已经创建了一个新的jobConf是的。。spark submit由root用户运行。您可以
导出HADOOP\u USER\u NAME=hdfs
,然后运行spark submit吗?我不这么做,因为它会全局影响sparkContext。我只是想写一些东西给hdfs作为“hdfs”用户。。。我们是否有办法将hadoop conf中的身份验证细节传递给spark api,它应该负责作为该用户写入hdfs?不这样做的另一个原因是,我可能希望使用不同的主机/端口/身份验证同时写入多个hdfs集群。为了确保这一点,您必须检查Spark源代码,并了解很多Hadoop身份验证的内部内容。但老实说,有多少人想这么做我的2美分:在本地文件系统中写下所有结果,然后使用纯Java代码创建多个
UserGroupInformation
&HDFS
filesystem
实例,然后将每个本地文件上载到其目标集群。祝你好运那些东西没有很好的记录。