并發(fā) kinit 導(dǎo)致 kerberos GSS initiate failed 定位與解決

線(xiàn)上任務(wù)調(diào)度工具執(zhí)行 Hadoop Hive 相關(guān)的任務(wù)會(huì)偶發(fā)任務(wù)執(zhí)行失敗的問(wèn)題,日志報(bào)錯(cuò)為 Kerberos 認(rèn)證失敗蝙泼。查看調(diào)度工具的運(yùn)行邏輯:每次執(zhí)行任務(wù)前先 kinit 認(rèn)證探孝,再執(zhí)行任務(wù)辩涝,考慮到最近遷移任務(wù)量大霍狰,且多為單個(gè)租戶(hù)的任務(wù),懷疑是該租戶(hù)并發(fā) kinit 導(dǎo)致砚哗,經(jīng)一系列的測(cè)試與驗(yàn)證婚陪,筆者確認(rèn)了問(wèn)題的原因,使用一種更優(yōu)的方案解決了集群租戶(hù)并發(fā)認(rèn)證的問(wèn)題频祝。

1.問(wèn)題發(fā)現(xiàn)

大數(shù)據(jù)平臺(tái) Hadoop 的安全認(rèn)證是基于 Kerberos 實(shí)現(xiàn)的泌参。 Kerberos 是一個(gè)網(wǎng)絡(luò)身份驗(yàn)證協(xié)議,用戶(hù)只需輸入身份驗(yàn)證信息常空,驗(yàn)證通過(guò)獲取票據(jù)即可訪(fǎng)問(wèn)多個(gè)接入 Kerberos 的服務(wù)沽一。

Kerberos 認(rèn)證方式有兩種:

  1. 使用密碼認(rèn)證:使用用戶(hù)密碼通過(guò) kinit 認(rèn)證, 獲取到的 TGT 存在本地憑證緩存當(dāng)中, 供后續(xù)訪(fǎng)問(wèn)服務(wù)認(rèn)證使用漓糙。一般在交互式訪(fǎng)問(wèn)中使用铣缠。
  2. 使用 keytab 認(rèn)證:用戶(hù)通過(guò)導(dǎo)出的 keytab 可以免密碼進(jìn)行用戶(hù)認(rèn)證, 后續(xù)步驟一致昆禽。一般在應(yīng)用程序中配置使用蝗蛙。

目前大數(shù)據(jù)平臺(tái)租戶(hù)執(zhí)行任務(wù),主要采用第一種 kinit 的方式實(shí)現(xiàn)認(rèn)證醉鳖, 為了保證 kerberos 認(rèn)證不過(guò)期捡硅,調(diào)度系統(tǒng)在每次執(zhí)行任務(wù)時(shí)會(huì)先 kinit 認(rèn)證刷新憑證 echo $passwd | kinit

這種方式簡(jiǎn)單可用盗棵,但最近總是頻發(fā)認(rèn)證失敗的問(wèn)題壮韭。報(bào)錯(cuò)如下:
GSS initiate failed: No valid credentials provided Failed to find any kerberos tgt

2.問(wèn)題定位

每次執(zhí)行前都會(huì) kinit,怎么會(huì)還找不到 kerberos tgt纹因,為了定位于解決問(wèn)題喷屋,我們先來(lái)看下 kinit 的解釋

kinit 命令用于獲取和緩存 principal 的初始票證授予票證(憑證)。此票證用于 Kerberos 系統(tǒng)進(jìn)行驗(yàn)證瞭恰。只有擁有 Kerberos 主體的用戶(hù)才可以使用 Kerberos 系統(tǒng)屯曹。有關(guān) Kerberos 主體的信息,請(qǐng)參見(jiàn) kerberos(5)。
當(dāng)使用 kinit 而未指定選項(xiàng)時(shí)恶耽,實(shí)用程序?qū)⑻崾灸斎?principal 和 Kerberos 口令僵井,并嘗試使用本地 Kerberos 服務(wù)器驗(yàn)證您的登錄。如果需要驳棱,可以在命令行上指定 principal。
如果登錄嘗試通過(guò)了 Kerberos 的驗(yàn)證农曲,kinit 將檢索您的初始票證授予票證并將其放到票證高速緩存中社搅。缺省情況下,票證存儲(chǔ)在 /tmp/krb5cc_uid 文件中乳规,其中 uid 表示用戶(hù)標(biāo)識(shí)號(hào)形葬。票證將在指定的生命周期后過(guò)期,之后必須再次運(yùn)行 kinit暮的。高速緩存中的任何現(xiàn)有內(nèi)容都將被 kinit 銷(xiāo)毀笙以。[1]

考慮到最近單個(gè)租戶(hù)的并發(fā)任務(wù)量大(大量任務(wù)在調(diào)度系統(tǒng)配置同一時(shí)間,定時(shí)調(diào)度)冻辩,懷疑是并發(fā) kinit 導(dǎo)致 - kinit 操作會(huì)重新覆蓋寫(xiě) krb 文件 - 即并發(fā)場(chǎng)景下有 krb 文件不可讀的情況猖腕。

為了驗(yàn)證猜想,做了如下測(cè)試:

  1. 刪除用戶(hù)的憑證文件: /tmp/krb5cc_uid恨闪,執(zhí)行 hdfs 命令倘感。報(bào)同樣的認(rèn)證錯(cuò)誤
  2. 編寫(xiě)測(cè)試腳本咙咽,并發(fā) kinit 后執(zhí)行 hdfs 任務(wù)老玛,此認(rèn)證報(bào)錯(cuò)問(wèn)題必現(xiàn)

3.問(wèn)題解決

如何保證租戶(hù)并發(fā)場(chǎng)景下钧敞,認(rèn)證成功且不過(guò)期蜡豹,想到兩種解決思路:

  1. 認(rèn)證失敗后重試,重新 kinit溉苛,必須封裝平臺(tái)級(jí) API 才行(并發(fā)依然可能出錯(cuò))
  2. 不用每次執(zhí)行任務(wù)都 kinit镜廉,改為定期按需進(jìn)行 kinit 認(rèn)證更新憑證 , 且保證并發(fā)的場(chǎng)景不出錯(cuò)

根據(jù)當(dāng)前場(chǎng)景,采用第二種方案愚战,簡(jiǎn)單快速桨吊,可實(shí)現(xiàn),這種方案的優(yōu)點(diǎn)如下:

  1. 按需 kinit凤巨,過(guò)濾絕對(duì)多數(shù)的重復(fù)的 kinit视乐, Kerberos KDC 認(rèn)證服務(wù)器的壓力可以降低 90% 以上。
  2. 最小化代碼入侵

解決過(guò)程如下:
首先通過(guò) klist 查看 認(rèn)證相關(guān)信息敢茁,如 ticket 的文件路徑和名稱(chēng)佑淀,失效時(shí)間等

[chenyao_yy@CD/WJ2FD-L350-ZYC1Q-colletion-DELLR730-SV013 ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_30022_3zIUZUTNbD
Default principal: chenyao_yy@KDC

Valid starting     Expires            Service principal
08/14/18 17:02:12  08/16/18 17:02:12  krbtgt/KDC@KDC
    renew until 08/21/18 17:02:12

每次執(zhí)行任務(wù)前,klist 查看票據(jù)失效時(shí)間彰檬,當(dāng)快要失效時(shí)(目前定義 2 hours)伸刃,才進(jìn)行 kinit谎砾,至此解決了按需 kinit 的問(wèn)題;

并發(fā)的問(wèn)題借鑒了鎖的概念捧颅,通過(guò)鎖互斥執(zhí)行 kinit景图。保證一次只有一個(gè)進(jìn)程能 kinit 成功。 經(jīng)查詢(xún) linux 有文件鎖的概念碉哑,經(jīng)測(cè)試可用 - flock[2]

3.1 Linux flock 文件鎖

簡(jiǎn)單說(shuō)下使用:
flock -xn /tmp/${user}_kinit_lock -c "echo $passwd | kinit"

  • 參數(shù)說(shuō)明:-x:獨(dú)占鎖 挚币;-n:未獲取到鎖立馬退出,避免阻塞
  • 獲取文件 /tmp/${user}_kinit_lock 獨(dú)占鎖扣典,獲取到才能執(zhí)行 kinit妆毕,執(zhí)行結(jié)束釋放鎖(租戶(hù)的文件鎖通過(guò)用戶(hù)名來(lái)區(qū)分)。
  • 未獲取到文件鎖直接退出(跳過(guò) -c 后的命令)

這里需要特殊說(shuō)明是:未獲取到鎖或者 -c 命令執(zhí)行失敗都會(huì)返回 1($?=1)

3.2 kinit 腳本實(shí)現(xiàn)

具體實(shí)現(xiàn)腳本如下:

#!/bin/bash
# kinit helper - 解決單用戶(hù)并發(fā) kinit 報(bào)錯(cuò)問(wèn)題
# 只有當(dāng) expiredTime 剩余時(shí)間小于 2 小時(shí)才進(jìn)行 kinit 操作贮尖,且只允許一次 kinit
source /etc/profile

# 輸入?yún)?shù) $1=租戶(hù) $2=租戶(hù)密碼
proxyUser=$1
passwd=$2
# 是否需要 kinit (默認(rèn)需要=0)
needKinit=0
# 過(guò)期剩余時(shí)間閾值 2 小時(shí)
let maxLeftTime=2*60*60

# 檢查是否需要重新 kinit笛粘,存在如下兩種情況:
# 1.krb 文件不存在
# 2.klist 過(guò)期時(shí)間,還剩不到 2 小時(shí)
check_if_need_kinit(){
  klist > /dev/null
  if [ $? -eq 0 ]; then

    # check principal is match
    principal=$(klist | awk '{print $3}' | sed -n '2p' | cut -d@ -f1)
    echo "default principal: $principal"
    if [ "$principal" != "${proxyUser}" ]; then
       echo "expect principal: $proxyUser, will re-kinit"
       return
    fi

    # check klist has renew info
    klist | grep renew
    if [ $? -eq 1 ]; then
       klist
       echo "klist info exception !"
       return
    fi

    expiredTime=$(klist | sed -n "5,1p" | awk '{print $2,$3}')
    expiredTimeFT=$(date -d "${expiredTime}" +"%Y-%m-%d %H:%M:%S")
    expiredTimestamp=$(date -d "$expiredTimeFT" +%s)
    currentTimestamp=$(date +%s)
    if [ $expiredTimestamp -gt $currentTimestamp ]; then
      let free=$expiredTimestamp-$currentTimestamp
      # 剩余時(shí)間大于所設(shè)閾值湿硝,則不需要 kinit
      if [ $free -gt $maxLeftTime ]; then
         nowTime=$(date "+%Y-%m-%d %H:%M:%S")
         echo "NowTime: $nowTime, ExpiredTime: $expiredTimeFT, no need to kinit!"
         needKinit=1
      fi
    fi
  else
    echo "krb file does not exist!"
  fi
}

# 傳入?yún)?shù)檢查
if [  $# != 2 -o "$proxyUser" = "" -o "$passwd" = "" ]; then
    echo "some curtionl params is null ! please check your prams"
    exit 1
fi

check_if_need_kinit
if [ $needKinit -eq 0 ]; then
  user=$(whoami)
  # 搶占獨(dú)占鎖薪前,進(jìn)行 kinit 操作
  echo "try to kinit, command: [ echo password | kinit $proxyUser ]"
  flock -xn /tmp/${user}_kinit_lock -c "echo '$passwd' | kinit $proxyUser"
  if [ $? -eq 0 ]; then
    echo "kinit success!"
  else
    echo "kinit faild: may be kinit by other concurrent process or password is incorret!"
  fi
fi

實(shí)際腳本中 考慮了認(rèn)證用戶(hù)錯(cuò)位 - principal 不匹配,認(rèn)證 klist 信息不全認(rèn)證失敗等場(chǎng)景关斜,較大程度提高了認(rèn)證的可用性序六。

參考:
[1] https://docs.oracle.com/cd/E56344_01/html/E54075/kinit-1.html
[2] http://www.jusene.me/2017/02/22/flock/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蚤吹,隨后出現(xiàn)的幾起案子例诀,更是在濱河造成了極大的恐慌,老刑警劉巖裁着,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件繁涂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡二驰,警方通過(guò)查閱死者的電腦和手機(jī)扔罪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)桶雀,“玉大人矿酵,你說(shuō)我怎么就攤上這事〈;” “怎么了全肮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)棘捣。 經(jīng)常有香客問(wèn)我辜腺,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任评疗,我火速辦了婚禮测砂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘百匆。我一直安慰自己砌些,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布加匈。 她就那樣靜靜地躺著存璃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矩动。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天释漆,我揣著相機(jī)與錄音悲没,去河邊找鬼。 笑死男图,一個(gè)胖子當(dāng)著我的面吹牛示姿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逊笆,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼栈戳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了难裆?” 一聲冷哼從身側(cè)響起子檀,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乃戈,沒(méi)想到半個(gè)月后褂痰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡症虑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年缩歪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谍憔。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鲤嫡,到底是詐尸還是另有隱情兄淫,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布苫昌,位于F島的核電站需忿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屋厘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一涕烧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汗洒,春花似錦议纯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至世杀,卻和暖如春阀参,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞻坝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工蛛壳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人所刀。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓衙荐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親浮创。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忧吟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容