赴海獨(dú)漂櫓,白首度餘生砸西。 -- 木心
Just For M
前言
為了梳理 apache sentry_1.5.0 開(kāi)啟 hdfs sync 功能后 不再支持hs2的Metastore HA 的原因器紧,最近把?HiveServer2 的部署架構(gòu)梳理了一遍叠纹,網(wǎng)上針對(duì)該類(lèi)信息的文章也非常少跨新,特地在這里整理出來(lái)剃盾,以供大家討論灶挟。
先描述一下我們的 HiveServer2 的部署背景琉朽,我們的大數(shù)據(jù)平臺(tái)是CDH, 整個(gè)平臺(tái)使用 KERBEROS 來(lái)進(jìn)行身份驗(yàn)證稚铣,權(quán)限控制使用的是 Sentry + Acls, 我們的 HiveServer2 服務(wù)使用 LDAP 或者 KERBEROS 來(lái)對(duì)用戶進(jìn)行身份驗(yàn)證箱叁,實(shí)際上開(kāi)啟 LDAP 驗(yàn)證的 HiveServer2 也是可以進(jìn)行 KERBEROS 驗(yàn)證的,但是 hive on spark 這個(gè)功能的開(kāi)啟惕医,導(dǎo)致了 HiveServer2 必須是 KERBEROS 驗(yàn)證的(他們使用了一個(gè)相同的config來(lái)進(jìn)行判斷提交任務(wù)是否需要 KERBEROS)耕漱。
一般情況下部署 HiveServer2 ,大家應(yīng)該很熟悉。Metastore 可以選擇是 內(nèi)嵌 還是 單獨(dú)部署抬伺,為了保證服務(wù)的高可用性(HA)螟够,我們可能會(huì)部署多臺(tái) HiveServer2 以及 多臺(tái) Metastore,他們也起到了負(fù)載均衡的效果沛简。而在安全的情況下齐鲤,配置的時(shí)候需要些許注意斥废,而 HiveServer2 內(nèi)部也會(huì)多執(zhí)行一些東西來(lái)保證認(rèn)證安全,下面我們所要講的就是這些流程给郊。
HiveServer2
圖例展示了一個(gè)通用的部署模式: HiveServer2 多臺(tái)牡肉,Metastore 多臺(tái),使用 mysql 等關(guān)系型數(shù)據(jù)庫(kù)來(lái)保存元數(shù)據(jù)信息淆九。 HiveServer2 如果需要修改元數(shù)據(jù)信息统锤,會(huì)將請(qǐng)求發(fā)送到 Metastore 。
HiveServer2 使用 Thrift 來(lái)進(jìn)行通信, 用戶使用 jdbc 或者 Thrift 連接到 HiveServer2; HiveServer2 每個(gè)執(zhí)行線程如果需要與后面的 Metastore 通信也是使用 Thrift 連接炭庙。
ThrfitSasl
看過(guò) kerberos體系下的應(yīng)用(yarn,spark on yarn) 的用戶可能已經(jīng)對(duì) ThrfitSasl 連接方式了解了饲窿,我們這里將描述一下通信過(guò)程:
- 我們的 ThrfitSasl 接受兩種驗(yàn)證, KERBEROS 認(rèn)證以及由自己下發(fā)給客戶端的 Token;
- Token 認(rèn)證是有時(shí)效性的,有最大刷新時(shí)間和失效時(shí)間焕蹄。
- 關(guān)于Token認(rèn)證逾雄,如果大家對(duì) HDFS 里面NameNode、DataNode 里面的 Token 的邏輯有所耳聞腻脏,閱讀 HiveServer2 Token邏輯鸦泳,會(huì)感覺(jué)似曾相識(shí),是的永品,hive里面的相關(guān)邏輯是借鑒 hadoop-common做鹰。
讓我們對(duì)其中的細(xì)節(jié)再深入思考一下。
KERBEROS認(rèn)證
- 如果 conf 沒(méi)有
hive.metastore.token.signature
鼎姐,選擇kerberos認(rèn)證方式钾麸,創(chuàng)建SaslClient的實(shí)現(xiàn)類(lèi)GssKrb5Client用于與 SaslServer 通信。 -
hive.server2.enable.doAs
為 false 的服務(wù)炕桨,均使用kerberos認(rèn)證饭尝,因?yàn)槲覀兊钠脚_(tái)使用 sentry 來(lái)做權(quán)限管理,所以是不允許 doAs 操作的谋作,提交任務(wù)的用戶均為hive 用戶芋肠。 - 這意味著運(yùn)行SaslClient端的服務(wù)上 UGI 要不斷更新,保持自己的
tgt遵蚜。 - 關(guān)于
javax.security.sasl
實(shí)現(xiàn)的邏輯帖池,這里不擴(kuò)展了,有興趣的可以查閱資料吭净,后面有機(jī)會(huì)會(huì)專(zhuān)門(mén)分析睡汹。
Token認(rèn)證
想一想,如果我們要效仿HDFS的Delegation Token邏輯寂殉,在實(shí)現(xiàn)上我們需要什么囚巴?
- 首先服務(wù)端要能夠生成有時(shí)效性的Token,并且有能判斷Token是否過(guò)期的能力。
- 因?yàn)樾枰赜?strong>hadoop-common中的token的數(shù)據(jù)結(jié)構(gòu)彤叉,我們返回的 Token 的格式應(yīng)該是繼承自 AbstractDelegationTokenIdentifier庶柿。 在Hive中,這個(gè)類(lèi)型為DelegationTokenIdentifier秽浇,其中KindName標(biāo)示為
HIVE_DELEGATION_KIND
浮庐。 - 返回的Token 將由UGI統(tǒng)一管理:
ugi.addToken(delegationToken)
- 我們知道UGI可能同時(shí)管理訪問(wèn)不同組件的多個(gè)Token,所以我們還應(yīng)該有個(gè)選擇
HIVE_DELEGATION_KIND
的選擇器:DelegationTokenSelector, 有了它,我們?cè)趧?chuàng)建 SaslClient的時(shí)候可以獲得對(duì)應(yīng)的Token:
上述應(yīng)該是使用 Token 認(rèn)證的各個(gè)部分的注意事項(xiàng)柬焕。
Token認(rèn)證-服務(wù)端
服務(wù)端(e.g: Metastore)使用 HiveDelegationTokenManager 來(lái)進(jìn)行Token管理审残。類(lèi)中主要包含了一個(gè)繼承自hadoop-common AbstractDelegationTokenSecretManager的 TokenStoreDelegationTokenSecretManager,也是我們這節(jié)探討的重點(diǎn)斑举。
-
Token生成
-
客戶端申請(qǐng)一個(gè)Token使用搅轿,服務(wù)端收到get_delegation_token請(qǐng)求時(shí)候(這次通信是kerberos認(rèn)證的),調(diào)用TokenStoreDelegationTokenSecretManager方法 getDelegationToken富玷。
-
TokenStoreDelegationTokenSecretManager 返回 Token璧坟,并且使用自己的 createPassword 方法為這個(gè)Token生成密碼。除了照搬hadoop-common里面的記錄Token的生命周期外凌彬,還額外的調(diào)用了tokenStore.addToken將我們的token信息保存進(jìn)了DelegationTokenStore中沸柔。
-
-
Token認(rèn)證
-
服務(wù)端認(rèn)證調(diào)用 SaslDigestCallbackHandler回調(diào)方法循衰,從nc中拿到客戶端傳遞過(guò)來(lái)的DelegationTokenIdentifier铲敛,在getPassword一步,服務(wù)端將做兩部驗(yàn)證会钝,第一伐蒋,這個(gè)Token是否存在;第二迁酸,這個(gè)Token是否過(guò)期先鱼。如果驗(yàn)證合格,則處理業(yè)務(wù)奸鬓。
-
-
Token清理
-
因?yàn)橐肓祟~外的存儲(chǔ)方式 DelegationTokenStore, 為了防止存儲(chǔ)數(shù)據(jù)無(wú)限膨脹焙畔,我們需要定時(shí)對(duì)服務(wù)端過(guò)期的Token進(jìn)行remove。
-
Token認(rèn)證-DelegationTokenStore
Metastore提供三種存儲(chǔ)方式:
- MemoryTokenStore
- DBTokenStore
- ZooKeeperTokenStore
第一種是內(nèi)存串远,這里不做解讀宏多,對(duì)于后兩者,為什么 Metastore 要把這部分?jǐn)?shù)據(jù)統(tǒng)一持久化呢澡罚?我們持久化的是什么信息伸但?我們持久化的大部分是可以使用的Token,當(dāng)驗(yàn)證Token認(rèn)證的客戶端的時(shí)候?qū)r(shí)候到這部分信息留搔。
如果我們部署了多臺(tái)Metastore, HiveServer2 隨機(jī)選擇一臺(tái)進(jìn)行連接操作更胖,如果我們打開(kāi)了doAs,那么我們業(yè)務(wù)線程連接Metastore將使用Token認(rèn)證。這個(gè)時(shí)候我們已經(jīng)連接的Metastore突然掛掉却妨,客戶端重連到了另外一臺(tái)Metastore上去饵逐,因?yàn)槲覀冎?strong>Metastore是無(wú)狀態(tài)的,所以重連到新的機(jī)器上不影響業(yè)務(wù)數(shù)據(jù)彪标。但是新的Metastore如果認(rèn)證這個(gè)Token梳毙? 是的!捐下! 因?yàn)樗鼈兊乃?strong>Metastore 所有的Token信息都是共享的账锹,新的Metastore 輕而易舉的就通過(guò)了重連的客戶端認(rèn)證。
總結(jié)
讀完全文之后坷襟,希望讀者重新查看本文的?HiveServer2-HA-架構(gòu)圖奸柬,其實(shí)想表達(dá)的邏輯都在圖中。這里需要重點(diǎn)注意的是婴程,我們?cè)诓渴?Metastore HA后廓奕,如果開(kāi)啟了Token認(rèn)證,請(qǐng)務(wù)必使用DBTokenStore或者ZooKeeperTokenStore档叔,否則HiveServer2與Metastore 的斷開(kāi)重連對(duì)用戶不透明桌粉。但是如果只會(huì)使用KERBEROS認(rèn)證,則不會(huì)存在Token共享問(wèn)題衙四。