java hdfs kerberos 认证超时 Receive timed out

背景

cdh6 集群为阿里服务器,三台机器搭建而成,并且开启了 kerberos,现在想尝试一下用 java api 读取 hdfs 数据。
代码如下:

public class ReadHdfsOnKerberos {

    public static void main(String[] args) throws IOException {
        String krbConfigPath = "D:\\Code\\kk-architecture-bigdata-practice\\Hadoop-Practice\\src\\main\\resources\\";
        System.setProperty("java.security.krb5.conf", krbConfigPath + "krb5.conf");

        Configuration conf = new Configuration();
        conf.set("hadoop.security.authentication", "Kerberos");
        conf.set("java.security.krb5.conf", krbConfigPath + "krb5.conf");

        UserGroupInformation.setConfiguration(conf);

        System.out.println("开始登录 kerberos");

        UserGroupInformation.loginUserFromKeytab("hdfs/[email protected]", krbConfigPath + "root.keytab");

        System.out.println("登录结束");

        String file = "hdfs://ip1:8020";
        FileSystem fs = FileSystem.get(URI.create(file), conf);

        System.out.println(fs.exists(new Path("/")));
    }
}

报错如下:

[2021-11-28 00:30:43 上午]:DEBUG org.apache.hadoop.security.UserGroupInformation$HadoopLoginModule.login(UserGroupInformation.java:222)hadoop login
Exception in thread "main" java.io.IOException: Login failure for hdfs/admin@KKARCH.COM from keytab D:\Code\kk-architecture-bigdata-practice\Hadoop-Practice\src\main\resources\root.keytab: javax.security.auth.login.LoginException: Receive timed out
	at org.apache.hadoop.security.UserGroupInformation.loginUserFromKeytab(UserGroupInformation.java:983)
	at com.kkarch.hadoop.rpc.kerberos.ReadHdfsOnKerberos.main(ReadHdfsOnKerberos.java:29)
Caused by: javax.security.auth.login.LoginException: Receive timed out
	at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:808)
	at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:617)
	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 javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
	at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
	at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
	at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
	at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
	at org.apache.hadoop.security.UserGroupInformation.loginUserFromKeytab(UserGroupInformation.java:974)
	... 1 more
Caused by: java.net.SocketTimeoutException: Receive timed out
	at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
	at java.net.DualStackPlainDatagramSocketImpl.receive0(DualStackPlainDatagramSocketImpl.java:124)
	at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:143)
	at java.net.DatagramSocket.receive(DatagramSocket.java:812)
	at sun.security.krb5.internal.UDPClient.receive(NetClient.java:206)
	at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:411)
	at sun.security.krb5.KdcComm$KdcCommunication.run(KdcComm.java:364)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.security.krb5.KdcComm.send(KdcComm.java:348)
	at sun.security.krb5.KdcComm.sendIfPossible(KdcComm.java:253)
	at sun.security.krb5.KdcComm.send(KdcComm.java:229)
	at sun.security.krb5.KdcComm.send(KdcComm.java:200)
	at sun.security.krb5.KrbAsReqBuilder.send(KrbAsReqBuilder.java:316)
	at sun.security.krb5.KrbAsReqBuilder.action(KrbAsReqBuilder.java:361)
	at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:776)
	... 14 more

Process finished with exit code 1

真是百思不得其解,初步怀疑是阿里云的端口没开。
kerberos 用了两个端口,一个是 88 ,kdc 在用;另一个是 749 , kadmin 在用,但是都开了:
java hdfs kerberos 认证超时 Receive timed out_第1张图片
打开 cmd ,telnet 88 和 749 端口,都是可以通的,但是报错始终提示,接收数据异常。

我一想,是不是出的方向我没配啊。但是它提示我,出方向始终是放行的
java hdfs kerberos 认证超时 Receive timed out_第2张图片
于是继续去服务器上看日志:
/var/log/krb5kdc.log
/var/log/kadmind.log
都没有新增的日志。

一筹莫展…陷入了僵局…

继续看本地的日志,突然发现,咦,这个 UDPClient,好像是在接收 udp 的请求,说明发出去的也是一个 udp 请求!
然而,阿里云的安全配置是区分 tcp 和 udp 的,我配的是一个 tcp 的策略。
java hdfs kerberos 认证超时 Receive timed out_第3张图片
于是赶紧改成了 udp
在这里插入图片描述

然后就特么可以了,搞了好久!!!

最后把 749 端口去掉,发现也是可以的,说明客户端认证只请求了 kdc 就可以完成认证了。

你可能感兴趣的:(开发问题汇总,spark,大数据,big,data)