概述:為解決臨時(shí)數(shù)據(jù)導(dǎo)致的集群資源爭(zhēng)用問題剃毒,我們采用了container日志分離方案病袄,但在Hadoop Security機(jī)制下,該方案存在跨集群的認(rèn)證問題赘阀。經(jīng)過對(duì)Hadoop Security機(jī)制及NodeMagager日志聚集功能源碼的分析益缠,探索了兩種解決方案:1)在各計(jì)算框架以個(gè)人用戶獨(dú)立認(rèn)證;2)在日志聚集功能模塊以Yarn用戶統(tǒng)一認(rèn)證基公,并對(duì)兩種解決方案的優(yōu)劣進(jìn)行了對(duì)比幅慌。
1 、概述
集群上的數(shù)據(jù)可以拆分為業(yè)務(wù)數(shù)據(jù)轰豆、臨時(shí)數(shù)據(jù)(日志胰伍、 app jars等),兩類數(shù)據(jù)(或其操作)共同爭(zhēng)用RPC, 存儲(chǔ)等資源酸休。經(jīng)統(tǒng)計(jì)骂租,每天NN RPC總量約為9.06億,其中斑司,存儲(chǔ)日志數(shù)據(jù)導(dǎo)致的RPC約占RPC總量的10%渗饮,為了降低計(jì)算集群的RPC壓力,我們結(jié)合YARN-3269提出了Container日志分離方案:將Container日志數(shù)據(jù)進(jìn)行聚集宿刮,然后存儲(chǔ)至獨(dú)立的用于存放冷數(shù)據(jù)的集群互站,從而消除日志存儲(chǔ)對(duì)計(jì)算集群的影響。
目前僵缺,集群采用了基于Kerberos的Hadoop Security機(jī)制云茸,而該安全機(jī)制會(huì)導(dǎo)致日志聚集功能中HDFSClient訪問冷數(shù)據(jù)集群NameNode認(rèn)證失敗,從而影響分離方案實(shí)施谤饭。
為了解決該問題标捺,保障分離方案順利實(shí)施懊纳,對(duì)Hadoop Security機(jī)制做了深入研究,并結(jié)合NodeManager日志聚集功能源碼分析亡容,探索了兩種解決方案:
1) 在各計(jì)算框架以個(gè)人用戶獨(dú)立認(rèn)證嗤疯。
2) 在日志聚集功能模塊以Yarn用戶統(tǒng)一認(rèn)證。
下文將對(duì)Hadoop Security 機(jī)制闺兢,日志分離功能遇到的問題的原因及解決方案進(jìn)行詳細(xì)分析茂缚,不足之處,也請(qǐng)批評(píng)指正屋谭。
2 脚囊、Hadoop Security
Hadoop Security機(jī)制采用Kerberos 與Delegation Tokens(代理Token)相結(jié)合的方案。
2.1 Kerberos
2.1.1 Kerberos 原理
為了更加形象的說明Kerberos的原理桐磁,我們采用舉例的方式進(jìn)行說明(官方示例)悔耘。
比如:用戶要去游樂場(chǎng),首先要在門口檢查用戶的身份(即 CHECK 用戶的 ID 和 PASS), 如果用戶通過驗(yàn)證我擂,游樂場(chǎng)的門衛(wèi) (AS) 即提供給用戶一張門卡 (TGT)衬以。
這張卡片的用處就是告訴游樂場(chǎng)的各個(gè)場(chǎng)所,用戶是通過正門進(jìn)來校摩,而不是后門偷爬進(jìn)來的看峻,并且也是獲取進(jìn)入場(chǎng)所一把鑰匙。
現(xiàn)在用戶有張卡衙吩,但是這對(duì)用戶來不重要互妓,因?yàn)橛脩魜碛螛穲?chǎng)不是為了拿這張卡的而是為了游覽游樂項(xiàng)目,這時(shí)用戶摩天樓坤塞,并想游玩车猬。
這時(shí)摩天輪的服務(wù)員 (client) 攔下用戶,向用戶要求摩天輪的 (ST) 票據(jù)尺锚,用戶說用戶只有一個(gè)門卡 (TGT), 那用戶只要把 TGT 放在一旁的票據(jù)授權(quán)機(jī) (TGS) 上刷一下珠闰。 票據(jù)授權(quán)機(jī) (TGS) 就根據(jù)用戶現(xiàn)在所在的摩天輪,給用戶一張摩天輪的票據(jù) (ST), 這樣用戶有了摩天輪的票據(jù)瘫辩,現(xiàn)在用戶可以暢通無阻的進(jìn)入摩天輪里游玩了伏嗜。
當(dāng)然如果用戶玩完摩天輪后,想去游樂園的咖啡廳休息下伐厌,那用戶一樣只要帶著那張門卡 (TGT). 到相應(yīng)的咖啡廳的票據(jù)授權(quán)機(jī) (TGS) 刷一下承绸,得到咖啡廳的票據(jù) (ST) 就可以進(jìn)入咖啡廳。
當(dāng)用戶離開游樂場(chǎng)后挣轨,想用這張 TGT 去刷打的回家的費(fèi)用军熏,對(duì)不起,用戶的 TGT 已經(jīng)過期了卷扮,在用戶離開游樂場(chǎng)那刻開始荡澎,用戶的 TGT 就已經(jīng)銷毀了均践。
如圖1所示,Kerberos認(rèn)證的過程可以分為三步:1)Client獲取KDC訪問許可TGT(我是誰)摩幔,2)向TGS請(qǐng)求要訪問的目標(biāo)服務(wù)的票具(我要干什么)彤委,3)訪問目標(biāo)服務(wù)(干什么),圖中具體流程與舉例說明相仿或衡,下面我們結(jié)合HDFS的訪問過程對(duì)其進(jìn)行描述焦影。
2.1.2 HDFS Client 的認(rèn)證流程
下面以大家常用的hdfs dfs – ls dir(或 hadoop fs –ls dir) 為例,描述Kerberos的認(rèn)證流程封断。
1) 首先使用kinit進(jìn)行登錄斯辰,輸入密碼后,Kerberos 客戶端收集user-principle(kinit時(shí)產(chǎn)生坡疼,可以使用Klist進(jìn)行查看) 和password彬呻,發(fā)送至KDC(AS)進(jìn)行認(rèn)證。
2) KDC認(rèn)證通過后回梧,下發(fā)TGT(user-kdc-ticket)給客戶端废岂∽娲辏客戶端收到TGT進(jìn)行校驗(yàn)通過后狱意,將TGT緩存在本地(用戶只讀)。
3) 將執(zhí)行hdfs dfs –ls dir時(shí)拯欧,首先從緩存中取出TGT, 然后向KDC(TGS)獲取連接NameNode(NN)訪問許可详囤。KDC收到請(qǐng)求,用戶身份校驗(yàn)通過后镐作,下發(fā)User-NN-Ticket.
4) HDFS客戶端使用得到的User-NN-Ticket連接NN藏姐。NN收到請(qǐng)求后,對(duì)Ticket進(jìn)行驗(yàn)證该贾,認(rèn)證通過后羔杨,使用加密數(shù)據(jù)回復(fù)客戶端,客戶端收到信任信息后杨蛋,發(fā)送listFiles(dir)請(qǐng)求兜材,并等待響應(yīng)。
以上為HDFS Client簡(jiǎn)要流程逞力,曙寡。
2.2 Delegation Token
理論上,可以單獨(dú)使用Kerberos進(jìn)行身份認(rèn)證寇荧,然而举庶,在Hadoop這樣的分布式系統(tǒng)中使用時(shí),存在一個(gè)問題:對(duì)于每一個(gè)Job, 如果所有的工作任務(wù)者使用TGT通過Kerberos TGS進(jìn)行身份認(rèn)證揩抡,那么Kerberos將很快成為瓶頸户侥。圖2中的紅線說明了問題:一個(gè)作業(yè)可能有數(shù)千個(gè)節(jié)點(diǎn)到節(jié)點(diǎn)的通信镀琉,導(dǎo)致相同的KDC通信量。事實(shí)上添祸,在大集群中會(huì)不經(jīng)意地在KDC上執(zhí)行分布式拒絕服務(wù)攻擊滚粟。
因此,引入了Delegation Token作為一種輕量級(jí)的認(rèn)證方法來補(bǔ)充Kerberos身份驗(yàn)證刃泌。Kerberos是三方協(xié)議凡壤;相比之下,Delegation Token認(rèn)證是兩方認(rèn)證協(xié)議耙替。引入Delegation Token之后的認(rèn)證過程如圖3所示亚侠。
為了簡(jiǎn)潔起見,圖3省略了Kerberos身份驗(yàn)證的步驟和任務(wù)分配的細(xì)節(jié)俗扇。假設(shè)硝烂,現(xiàn)在已經(jīng)完成了Kerberos的三步式認(rèn)證,后續(xù)流程如下(KMS Delegation與HDFS Delegation協(xié)同铜幽,下面統(tǒng)一以HDFS的角度進(jìn)行說明):
1)Client在進(jìn)行完Kerberos的三步式認(rèn)證后滞谢,獲得NameNode產(chǎn)生的HDFS Delegation Token,并緩存于UGI.
2)Client 向RM(ResourceManager)提交App時(shí)除抛,會(huì)攜帶該Token信息狮杨。
3)RM接到Token之后, 會(huì)馬上對(duì)Token進(jìn)行Renew操作已驗(yàn)證其合法性,并將其持久化到要啟動(dòng)ApplicationMaster的Worker(NodeManager)到忽,Worker在啟動(dòng)ApplicationMaster加載該Token(后續(xù)Worker類似)橄教。
4)Worker 通過Token 對(duì)HDFS進(jìn)行訪問。
5)運(yùn)行結(jié)束喘漏,RM撤銷Token.
圖3 Delegation Token 補(bǔ)充方案認(rèn)證流程
值得注意的是护蝶,Token具有超時(shí)時(shí)間,默認(rèn)為24小時(shí)翩迈。在不對(duì)Token更新的情況下持灰,超過24小時(shí)的App將會(huì)失敗。因此负饲,存在Renewer對(duì)Token進(jìn)行更新以保證長(zhǎng)任務(wù)執(zhí)行(token最終超時(shí)時(shí)間由yarn參數(shù)delegation.token.max-lifetime決定)堤魁。
3 、日志聚集功能
3.1 日志分離失敗case
在原有配制基礎(chǔ)上绽族,開啟日志分離功能(跨集群日志聚集)后姨涡,發(fā)現(xiàn)未按預(yù)期進(jìn)行日志分離,且NodeManager節(jié)點(diǎn)存在以下異常信息:
2018-05-09 17:36:02,539 ERROR logaggregation.LogAggregationService (LogAggregationService.java:run(340)) - Failed to
setup application log directory for application_1525801833018_0004
java.io.IOException: Failed on local exception: java.io.IOException: org.apache.hadoop.security.AccessControlExcepti
on: Client cannot authenticate via:[TOKEN, KERBEROS]; Host Details : local host is: "*"; destination host is: "*";
通過觀察日志吧慢,可以清晰的發(fā)現(xiàn)涛漂,該異常系權(quán)限認(rèn)證失敗所致。通過分析源碼,該異常發(fā)生的位置進(jìn)行的操作為:通過userUGI.doAs創(chuàng)建AppLogDir匈仗。日志顯示的結(jié)果可能為userUGI中沒有訪問遠(yuǎn)程集群的Token瓢剿,導(dǎo)致失敗。
3.1.1 UGI 追蹤(UGI****從哪里來)
分析userUGI中是否具有訪問冷數(shù)據(jù)集群的Token, 我們需要對(duì)UGI的來源進(jìn)行跟蹤悠轩。通過分析源碼间狂,我們發(fā)現(xiàn)UGI關(guān)聯(lián)的User及Token(圖中Credentials為工具類,用于讀寫存儲(chǔ)在內(nèi)存或磁盤中密鑰和令牌)是通過解析LogAggregationServicer接收的APPLICATION_STARTED Event 得到的火架,具體跟蹤流程如圖4所示鉴象,其中Hander, Initializer為方便說明,抽象出來的對(duì)象何鸡。
根據(jù)時(shí)序圖中訪問流程纺弊,結(jié)合異常日志信息,可以確定異常原因的確userUGI沒有訪問遠(yuǎn)程集群的Toket(Credentials)
3.1.2 Credentials ( 或Tokens) 追蹤(Creadential 從哪里來)
本節(jié)從Spark計(jì)算引擎的角度骡男,對(duì)Credentials(或Tokens)來源進(jìn)行追蹤淆游。通過分析yarn/Client源碼,Client在啟動(dòng)AM (ApplicationMaster)前隔盛,會(huì)進(jìn)行一系列準(zhǔn)備工作犹菱。準(zhǔn)備工作過程中存在與其它組件的通信,其中包括準(zhǔn)備本地資源時(shí)(prepareLocalResources)與NN(NameNode)的通信:1)通過TGT 獲取user-nn-ticket(Client啟動(dòng)在客戶機(jī)吮炕,可以使用TGT) 腊脱;2)使用user-nn-ticket 訪問NN,并獲取Delegation Tokens. 獲取到Tokens后會(huì)通過Credentials將Tokens(不含TGT)存儲(chǔ)在ContainerLaunchContext中来屠。并隨同ApplicationSubmissionContext一起提交至Yarn虑椎,請(qǐng)求啟動(dòng)AM震鹉;Yarn收到請(qǐng)求后俱笛,會(huì)為其選擇NodeManager,使用ContainerLaunchContext 拉起AM.
從上圖可知,最后LogAggregationServicer可使用的Tokens是客戶端(Agent)初始化時(shí)传趾,獲取的迎膜。換句話說,客戶端獲取了訪問某NN的Token時(shí)浆兰,LogAggregationServicer才具有訪問該NN的Token. 而默認(rèn)情況下磕仅,客戶端僅會(huì)獲取fs.defaultFS(HADOOP_CONF:core-site.xml中配置),因此簸呈,跨集群訪問時(shí)無訪問日志集群的權(quán)限榕订。
3.2 解決方案
通過上述分析可知,若想訪問某服務(wù)蜕便,需具備以下一種條件:
1) 擁有該服務(wù)授予的合法Token.
2) 角色持用TGT(password認(rèn)證或keytabs),可以通過Kerberos完成完整的服務(wù)認(rèn)證劫恒。
基于以上分析,我們對(duì)日志分離認(rèn)證問題提出了兩種方案:
1)各計(jì)算框架以個(gè)人用戶獨(dú)立認(rèn)證
該方案的核心思想是向Yarn提交應(yīng)用前,使客戶端(Agent)獲取所有必要的Token两嘴〈猿客戶端啟動(dòng)在使用kinit進(jìn)行登錄的客戶機(jī),因此其可使用TGT 完成Kerberos認(rèn)證憔辫,并可以獲取到任務(wù)想訪問的服務(wù)(類2.1.1節(jié)流程)趣些。
因此,針對(duì)日志分離跨集群認(rèn)證問題贰您,應(yīng)使客戶端在向Yarn提交應(yīng)用前坏平,獲取到所有NN 的Token,以便傳遞到NM以用戶身份進(jìn)行日志聚集操作锦亦。
該方案需要在各計(jì)算引擎進(jìn)行配置或修改功茴,以使在提交應(yīng)用前,獲取到所需的Tokens.目前孽亲,Spark(“spark.yarn.access.namenodes”)及MR(“ mapreduce.job.hdfs-servers”)引擎坎穿,自帶配制參數(shù),用于指定額外的NN返劲,以獲取Tokens玲昧。其它引擎目前未進(jìn)行調(diào)研。
2 )日志聚集功能模塊以Yarn****用戶統(tǒng)一認(rèn)證
該方案的核心思想是使用NodeManager的啟動(dòng)用戶Yarn進(jìn)行日志聚集篮绿,從而使用Yarn統(tǒng)一進(jìn)行認(rèn)證孵延。
NodeManager使用KeyTabs方式進(jìn)行登錄,其可以通過Kerberos認(rèn)證訪問所有服務(wù)(包括NN)亲配;另外尘应,日志聚集功能,以AbstractService方式運(yùn)行于NodeManger吼虎。因此犬钢,理論上可以使用NodeManager獲取的Tokens 訪問遠(yuǎn)程N(yùn)N,創(chuàng)建日志目錄或上傳日志等思灰。
日志聚集不僅包括日志上傳等工作玷犹,還包括container本地日志清理工作,而Container日志的管理是以應(yīng)用提交用戶的名義進(jìn)行的管理洒疚,若直接將UserUGI簡(jiǎn)單的更換成NodeManager LoginUGI歹颓,則日志后處理工作將無法進(jìn)行,因此油湖,我們采用Token劫持方案進(jìn)行實(shí)現(xiàn)(若集群支持ProxyUser巍扛,可使用ProxyUser),即:使用用戶的UGI + NodeManager 獲取的Token方式進(jìn)行實(shí)現(xiàn)乏德,具體如下:
//Get the cerdentials that NM connects to remote NN and use it replace user's credentials.
try {
credentials = new Credentials();
FileSystem remoteFs = getFileSystem(getConfig());
remoteFs.addDelegationTokens(UserGroupInformation.getLoginUser().getShortUserName(), credentials);
} catch (IOException e) {
LOG.warn("Get credential failed for application: " + appId);
throw new YarnRuntimeException(e);
}
// Get user's FileSystem credentials
final UserGroupInformation userUgi =
UserGroupInformation.createRemoteUser(user);
if (credentials != null) {
userUgi.addCredentials(credentials);
}
3.3 方案對(duì)比
表1 跨集群日志分離認(rèn)證問題解決方案對(duì)比
對(duì)比項(xiàng) | 獨(dú)立認(rèn)證 | 統(tǒng)一認(rèn)證 |
---|---|---|
方案 | 向Yarn提交應(yīng)用前撤奸,客戶端(Agent)以登錄用戶身份獲取所有必要的Token | 劫持NodeManager的Token ,使用Yarn用戶進(jìn)行統(tǒng)一認(rèn)證 |
日志Owner | 使用用戶獲取NN Token,日志文件Owner為用戶 | 使用劫持NM獲取的NN Token寂呛,日志文件Owner為NM啟動(dòng)用戶Yarn怎诫, 因此需要借助Ranger進(jìn)行授權(quán) |
擴(kuò)展性 | 需要各計(jì)算引擎分別適配,以便 Agent中獲取到日志集群NN的Token | 計(jì)算引擎無需關(guān)心日志聚集所需NN Token |
魯棒性 | 初始化時(shí)贷痪,需要連接的多個(gè)NN以獲取所有Tokens, 當(dāng)日志NN不可達(dá)時(shí)幻妓,應(yīng)用將因連接異常而無法提交 | 日志NN不可達(dá)時(shí),僅影響日志聚集劫拢,不影響應(yīng)用提交 |
綜上肉津,我們采用日志聚集功能模塊以Yarn用戶統(tǒng)一認(rèn)證的方式來解決跨集群日志分離認(rèn)證問題。
4 結(jié)論
本文分析了Hadoop Security的原理舱沧,提出了兩種跨集群日志分離認(rèn)證問題解決方案妹沙。并對(duì)比了兩種方案的優(yōu)劣,最終選用日志聚集功能模塊以Yarn用戶統(tǒng)一認(rèn)證方案解決跨集群日志分離認(rèn)證問題熟吏,現(xiàn)該方案已上線驗(yàn)證距糖,截止目前運(yùn)行良好。
參考文獻(xiàn)
[1] Hadoop Delegation Tokens Explained :https://blog.cloudera.com/blog/2017/12/hadoop-delegation-tokens-explained/
[2] https://zh.wikipedia.org/wiki/Kerberos
[3]https://github.com/Tianny/Bloggy/issues/4