使用java client訪問kerberos-secured cluster,最重要的是先從admin那里拿到可用的keytab文件,用來作認證。接下來就是調整連接的配置。以下先用連接hdfs為例進行說明。
申請可用的keytab文件
1. 申請可認證的keytab文件,keytab文件用來存儲principal的key。由KDC那邊生成的principal,最終可以存儲在keytab文件中。
2. 安裝Kerberos client常用命令,並熟悉kerberos認證原理。
3. 配置/etc/krc5.conf,作為kerberos client端需要指明KDC的位置。
配置連接參數
由於直接用java應用程序去測試鏈接不太方便,這里推薦通過執行Hadoop command來測試是否能連接成功。
1. kinit 認證
kinit -kt path-to-keytab principalName
先認證principalName是否合法。如果合法,KDC會返回initial TGT。該TGT有效期通常是幾個小時。
2. 執行Hadoop命令
hadoop fs -ls hdfs://namenode1:8020
執行這個命令之后,會返回兒各種exception,按照exception的提示,逐步添加配置,如下:
1) 配置使用kerberos認證
hadoop.security.authentication: kerberos
2)Failed to specify server's Kerberos principal name
dfs.namenode.kerberos.principal
3)Server has invalid Kerberos principal
配置完2)后,如果返回 Server has invalid Kerberos principal,這個時候可以從以下三個方面考慮:
- Server principal是否合法或者配置正確,正常情況下將dfs.namenode.kerberos.principal設置成namenode configuration一致就可以了。
- DSN resolver是否一致。The HDFS client will initiate an RPC call to the namenode to get the hdfs service principal. Then the client with compare the hostname from the service princpal to the canonical name of the namenode hostname. In this case the namenode canonical name on the client machine resolved to a different hostname then what was in DNS.
- 如果以上兩種情況都正常,exception無法幫助我們鎖定問題,可用嘗試排除最大限度排除不定因素,縮小問題搜索范圍。比如安裝和server一樣的Hadoop版本,並且保持配置一致。如果command能執行成功,那么可用逐步減去lib, conf屬性,從而鎖定exception的本質原因。
Java Kerberos認證代碼
public class HadoopSecurityUtil { public static final String EAGLE_KEYTAB_FILE_KEY = "eagle.keytab.file"; public static final String EAGLE_USER_NAME_KEY = "eagle.kerberos.principal"; public static void login(Configuration kConfig) throws IOException { if (kConfig.get(EAGLE_KEYTAB_FILE_KEY) == null || kConfig.get(EAGLE_USER_NAME_KEY) == null) return; kConfig.setBoolean("hadoop.security.authorization", true); kConfig.set("hadoop.security.authentication", "kerberos"); UserGroupInformation.setConfiguration(kConfig); UserGroupInformation.loginUserFromKeytab(kConfig.get(EAGLE_USER_NAME_KEY), kConfig.get(EAGLE_KEYTAB_FILE_KEY)); } }
配置示例
- HDFS
{ "fs.defaultFS":"hdfs://nameservice1", "dfs.nameservices": "nameservice1", "dfs.ha.namenodes.nameservice1":"namenode1,namenode2", "dfs.namenode.rpc-address.nameservice1.namenode1": "hadoopnamenode01:8020", "dfs.namenode.rpc-address.nameservice1.namenode2": "hadoopnamenode02:8020", "dfs.client.failover.proxy.provider.apollo-phx-nn-ha": "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider", "eagle.keytab.file":"/EAGLE-HOME/.keytab/b_eagle.keytab_apd", "eagle.kerberos.principal":"eagle@EXAMPLE.COM" }
- HBase
{ "hbase.zookeeper.property.clientPort":"2181", "hbase.zookeeper.quorum":"localhost", "hbase.security.authentication":"kerberos", "hbase.master.kerberos.principal":"hadoop/_HOST@EXAMPLE.COM", "zookeeper.znode.parent":"/hbase", "eagle.keytab.file":"/EAGLE-HOME/.keytab/eagle.keytab", "eagle.kerberos.principal":"eagle@EXAMPLE.COM" }
References
- https://github.com/randomtask1155/HadoopDNSVerifier
- https://support.pivotal.io/hc/en-us/articles/204391288-hdfs-ls-command-fails-with-Server-has-invalid-Kerberos-principal
