以hadoop为例,其他hbase或者hive等组件一样的原理,dfs.datanode.kerberos.principal
的值为dn/_HOST@WOOPLE.COM
,那么这里principal为什么要使用_HOST
,可以参考官方的HADOOP-6632或者HADOOP-8098。
源码分析
本文源码基于hadoop2.7.2,简言之,在运行时会动态的将_HOST
替换为所在主机的hostname。
在SecurityUtil.java
中,下面的方法会替换_HOST
public static String getServerPrincipal(String principalConfig,
InetAddress addr) throws IOException {
String[] components = getComponents(principalConfig);
if (components == null || components.length != 3
|| !components[1].equals(HOSTNAME_PATTERN)) {
return principalConfig;
} else {
if (addr == null) {
throw new IOException("Can't replace " + HOSTNAME_PATTERN
+ " pattern since client address is null");
}
return replacePattern(components, addr.getCanonicalHostName());
}
}
再看一下如何获取主机的hostname
private static String replacePattern(String[] components, String hostname)
throws IOException {
String fqdn = hostname;
if (fqdn == null || fqdn.isEmpty() || fqdn.equals("0.0.0.0")) {
fqdn = getLocalHostName();
}
return components[0] + "/" +
StringUtils.toLowerCase(fqdn) + "@" + components[2];
}
最终下面的方法获取到机器的hostname,将_HOST
替换掉
static String getLocalHostName() throws UnknownHostException {
return InetAddress.getLocalHost().getCanonicalHostName();
}
总结
在多实例的组件中,例如nodemanager或者datanode等,它们的principal name中一般都带有_HOST
,在运行时会根据各个实例所在节点的真实的hostname将_HOST
替换掉,保证了每个节点使用的是自己主机实例的principal。
网友评论