【发布时间】:2016-05-21 10:13:00
【问题描述】:
我正在尝试使用以下代码连接到 Kerberized hdfs 集群,使用以下相同的代码,我当然可以使用 HBaseConfiguration 访问 hbase,
Configuration config = new Configuration();
config.set("hadoop.security.authentication", "Kerberos");
UserGroupInformation.setConfiguration(config);
UserGroupInformation ugi = null;
ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI("me@EXAMPLE>COM","me.keytab");
model = ugi.doAs((PrivilegedExceptionAction<Map<String,Object>>) () -> {
testHadoop(hcb.gethDFSConfigBean());
return null;
});
我已经能够使用相同的 keytab 和主体成功访问 Solr、Impala,我得到这个奇怪的 Failed to find service name for hdfs。
请看下面的堆栈跟踪
java.io.IOException: Failed on local exception: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name; Host Details : local host is: "Securonix-int3.local/10.0.4.36"; destination host is: "sobd189.securonix.com":8020;
at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:772)
at org.apache.hadoop.ipc.Client.call(Client.java:1472)
at org.apache.hadoop.ipc.Client.call(Client.java:1399)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:232)
at com.sun.proxy.$Proxy9.getFileInfo(Unknown Source)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.getFileInfo(ClientNamenodeProtocolTranslatorPB.java:752)
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:497)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:187)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
at com.sun.proxy.$Proxy10.getFileInfo(Unknown Source)
at org.apache.hadoop.hdfs.DFSClient.getFileInfo(DFSClient.java:1988)
at org.apache.hadoop.hdfs.DistributedFileSystem$18.doCall(DistributedFileSystem.java:1118)
at org.apache.hadoop.hdfs.DistributedFileSystem$18.doCall(DistributedFileSystem.java:1114)
at org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81)
at org.apache.hadoop.hdfs.DistributedFileSystem.getFileStatus(DistributedFileSystem.java:1114)
at org.apache.hadoop.fs.FileSystem.exists(FileSystem.java:1400)
at com.securonix.application.ui.uiUtil.SnyperUIUtil.lambda$main$4(SnyperUIUtil.java:1226)
at com.securonix.application.ui.uiUtil.SnyperUIUtil$$Lambda$6/1620890840.run(Unknown Source)
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:1628)
at com.securonix.application.ui.uiUtil.SnyperUIUtil.main(SnyperUIUtil.java:1216)
Caused by: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name
at org.apache.hadoop.ipc.Client$Connection$1.run(Client.java:680)
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:1628)
at org.apache.hadoop.ipc.Client$Connection.handleSaslConnectionFailure(Client.java:643)
at org.apache.hadoop.ipc.Client$Connection.setupIOstreams(Client.java:730)
at org.apache.hadoop.ipc.Client$Connection.access$2800(Client.java:368)
at org.apache.hadoop.ipc.Client.getConnection(Client.java:1521)
at org.apache.hadoop.ipc.Client.call(Client.java:1438)
... 23 more
Caused by: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name
at org.apache.hadoop.security.SaslRpcClient.getServerPrincipal(SaslRpcClient.java:322)
at org.apache.hadoop.security.SaslRpcClient.createSaslClient(SaslRpcClient.java:231)
at org.apache.hadoop.security.SaslRpcClient.selectSaslClient(SaslRpcClient.java:159)
at org.apache.hadoop.security.SaslRpcClient.saslConnect(SaslRpcClient.java:396)
at org.apache.hadoop.ipc.Client$Connection.setupSaslConnection(Client.java:553)
at org.apache.hadoop.ipc.Client$Connection.access$1800(Client.java:368)
at org.apache.hadoop.ipc.Client$Connection$2.run(Client.java:722)
at org.apache.hadoop.ipc.Client$Connection$2.run(Client.java:718)
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:1628)
at org.apache.hadoop.ipc.Client$Connection.setupIOstreams(Client.java:717)
启用 Kerberos 的调试代码后,当我调用 FileSystem.get(); 时,我得到了以下调试日志; Kerberor 调试日志:
Java 配置名称:null Java 配置名称:null
本机配置名称:/etc/krb5.conf 本机配置名称:/etc/krb5.conf
从本机配置加载 从本机配置加载
16/02/22 15:53:14 WARN util.NativeCodeLoader:无法为您的平台加载 native-hadoop 库...在适用的情况下使用内置 java 类
Java 配置名称:空 Java 配置名称:空
本机配置名称:/etc/krb5.conf 本机配置名称:/etc/krb5.conf
从原生配置加载 从原生配置加载
KdcAccessibility: 重置 >>> KdcAccessibility: 重置 KdcAccessibility: 重置 >>> KdcAccessibility: 重置 KeyTabInputStream,readName():EXAMPLE.COM >>> KeyTabInputStream,readName():EXAMPLE.COM KeyTabInputStream, readName(): securonix >>> KeyTabInputStream, readName(): securonix KeyTab:load() 条目长度:55;类型:23 >>> KeyTab:load() 条目长度:55;类型:23 KeyTabInputStream,readName():EXAMPLE.COM >>> KeyTabInputStream,readName():EXAMPLE.COM KeyTabInputStream, readName(): securonix >>> KeyTabInputStream, readName(): securonix KeyTab:load() 条目长度:71;类型:18 >>> KeyTab:加载()条目长度:71;类型:18 寻找密钥:securonix@EXAMPLE.COM 寻找密钥:securonix@EXAMPLE.COM 添加密钥:18 版本:1 添加密钥:18 版本:1 添加密钥:23version:1 添加密钥:23version:1 寻找密钥:securonix@EXAMPLE.COM 寻找密钥:securonix@EXAMPLE.COM 添加密钥:18 版本:1 添加密钥:18 版本:1 添加密钥:23version:1 添加密钥:23version:1 default_tkt_enctypes 的默认 etypes:18 18 16。 default_tkt_enctypes 的默认 etypes:18 18 16。 KrbAsReq 创建消息 >>> KrbAsReq 创建消息 KrbKdcReq 发送:kdc=sobd189.securonix.com TCP:88, timeout=30000, 重试次数 =3, #bytes=139 >>> KrbKdcReq 发送: kdc=sobd189.securonix.com TCP:88, timeout=30000, number重试次数=3,#bytes=139 KDCCommunication: kdc=sobd189.securonix.com TCP:88, timeout=30000,Attempt =1, #bytes=139 >>> KDCCommunication: kdc=sobd189.securonix.com TCP:88, timeout=30000,Attempt =1, #字节=139 调试:TCPClient 读取 639 字节 >>>DEBUG:TCPClient 读取 639 字节 KrbKdcReq 发送:#bytes 读取=639 >>> KrbKdcReq 发送:#bytes 读取=639 KdcAccessibility:删除 sobd189.securonix.com >>> KdcAccessibility:删除 sobd189.securonix.com 寻找密钥:securonix@EXAMPLE.COM 寻找密钥:securonix@EXAMPLE.COM 添加密钥:18 版本:1 添加密钥:18 版本:1 添加密钥:23version:1 添加密钥:23version:1 EType:sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType >>> EType:sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType KrbAsReq.getReply securonix 中的 KrbAsRep 缺点
有趣的是,当我使用 hdfs.exists() 等文件系统的 api 时
>>>KinitOptions cache name is /tmp/krb5cc_501
>> Acquire default native Credentials
default etypes for default_tkt_enctypes: 18 18 16.
>>> Found no TGT's in LSA
【问题讨论】:
-
基于 Steve Loughran 的技巧包 (steveloughran.gitbooks.io/kerberos_and_hadoop/content/sections/…) 获取一些 UGI 调试信息的关键是 (1) env 变量
HADOOP_JAAS_DEBUG(2) JVM系统属性sun.security.krb5.debug -
我将添加我自己的技巧:(3)
java.security.debug设置为 "gssloginconfig,configfile,configparser,logincontext" (docs.oracle.com/javase/7/docs/technotes/guides/security/…) 因为最常见的 Kerberos 错误来自您的自定义 JAAS 和 KRB5 conf 文件。 -
嗨 Samson,感谢您的回复和建议,所以我添加了调试语句并发现了一些有趣的东西,代码正确获取文件系统对象但是当我使用文件系统调用 exists() 方法时对象我得到相同的无法指定服务器的 Kerberos 主体名称错误 Kerberor 调试代码:
标签: java hadoop kerberos cloudera keytab