您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Kerberos環境下Java應用程序認證超時異常是怎么回事的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
測試環境
1.CM和CDH版本為5.15.1
2.操作系統版本為RedHat7.2
3.集群已啟用Kerberos
問題描述
在使用JDK 8時,在Kerberos環境下應用程序在執行的過程中報以下錯誤:
Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]
問題分析
在Kerberos環境下長時間運行的作業會出現認證失敗問題,認證失敗是由于Ticket過期導致。Ticket過期是由ticket_lifetime和renew_lifetime兩個參數控制,具體分析如下:
先了解下krb5.conf里ticket_lifetime和renew_lifetime參數:
ticket_lifetime = 24h
renew_lifetime = 7d
注:這里其實還跟kdc.conf里的ticket_lifetime和renew_lifetime相關,本文不做討論,假設你配置都是一致的。
每一個Kerberos的ticket,包括TGT,都有一個ticket_lifetime(默認:1天);Ticket可以被延續,但最多只能延續到renew_lifetime(默認:7天),超過7天后無法再延續,此時ticket失效,只能重新login。
如果你的應用程序需要運行很長時間或者需要持續不斷地一直運行,就會有一個問題,即:
在應用程序啟動時進行Kerberos認證登錄后,是否還需要定時renew ticket或在ticket期滿失效后使用keytab重新login?例如,是否需要在應用程序代碼里,在每個UGI.doAS(...)前調用UGI.checkTGTAndReloginFromKeytab或者使用一個Timer周期性地調用UGI.checkTGTAndReloginFromKeytab?
關于這個問題,首先需要了解在Hadoop系統里是如何進行Kerberos認證的:
Hadoop Kerberos認證的主要使用場景是Hadoop RPC框架(使用SASL進行kerberos認證)。大部分Hadoop daemon進程在啟動時會調用UGI(org.apache.hadoop.security.UserGroupInformation),UGI.loginUserFromKeytab做kerberos認證并獲取ticket,并在后續每一次RPC調用時使用該ticket認證。比如,DataNode必須認證它對NameNode的RPC調用,NodeManager也必須認證它對ResourceManager的RPC調用。那么,這些daemon進程為什么能在啟動后長時間持續運行而不會出現kerberos ticket錯誤呢(甚至已經超過了renew_lifetime)?這是因為Hadoop在RPC Client層實現了一種自動relogin機制。在Client.handleSaslConnectionFailure(org.apache.hadoop.ipc.Client)方法里有如下代碼:
// try re-login
if (UserGroupInformation.isLoginKeytabBased()) {
UserGroupInformation.getLoginUser().reloginFromKeytab();
} else if (UserGroupInformation.isLoginTicketBased()) {
UserGroupInformation.getLoginUser().reloginFromTicketCache();
}
上述代碼說明在使用RPC連接時,如果因為ticket失效造成認證失敗,會自動relogin。
基于以上認識,可以得出以下結論:
1.如果應用程序的使用模式是從keytab登錄后執行典型的Hadoop RPC Java調用(如調用HDFS FileSystem API),那么是不需要在應用層增加renew ticket或relogin代碼的,因為RPC Client層已經幫你實現了。
2.如果應用程序的使用模式是不使用Hadoop RPC,而是調用HDFS REST API或YARN REST API(使用SPNEGO進行kerberos認證),那么需要在應用程序里增加relogin代碼。具體實現方式是:
Java方式:主Java程序使用keytab調用UGI.loginUserFromKeytab登錄,然后在每個UGI.doAS前調用UGI.checkTGTAndReloginFromKeytab方法,或者另啟動一個線程周期性調用該方法。
Shell方式:主程序使用kinit登錄,然后啟動另一個子進程周期性的調用kinit -R去renew ticket或者調用kinit -kt去relogin。
需要注意的是當使用JDK 8時,UGI的relogin存在一個bug,即HADOOP-10786。該bug是因為JDK 8的Krb5LoginModule有些小改動,這些改動會造成UGI的relogin代碼認為之前的登錄并不是基于keytab登錄的。所以,UGI.reloginFromKeytab和UGI.checkTGTAndReloginFromKeytab方法實際上什么都沒有做,并沒有執行relogin。所以,此時應用程序仍然會報以下錯誤:
Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]
解決辦法
對于使用JDK 8應用程序不能正常reloginFromKeytab的 bug,workaround是:
1. 使用JDK 7而不是JDK 8,或者
2. 確保hadoop-common包含了HADOOP-10786補丁。
建議使用CDH5.13.0或者以上版本的包,這些包已經包括了該補丁。如果仍然在IDE開發環境出現了以上問題,可以檢查一下IDE依賴的hadoop-common包的版本是否有問題。
感謝各位的閱讀!關于“Kerberos環境下Java應用程序認證超時異常是怎么回事”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。