天天看點

Isito從懵圈到熟練 - 半夜兩點Ca證書過期問題處理慘況總結

作者:shengdong

11月22号半夜2點,被值班同學的電話打醒。了解下來,大概情況是,客戶某一台K8s叢集節點重新開機之後,他再也無法建立Istio虛拟服務和Pod了。

一來對Istio還不是那麼熟悉,二來時間可能有點晚,腦子還在懵圈中,本來一個應該比較輕松解決掉的問題,花了幾十分鐘看代碼,處理的慘不忍睹。最終還是在某位大神幫助下,解決了問題。

鑒于此問題,以及相關報錯,在網上找不到對應的文章,是以這裡分享下這個問題,避免後來的同學,在同樣的地方踩坑。另外謹以此篇緻敬工作中遇到過的大神!

不斷重新開機的Citadel

Citadel是istio的證書分發中心。證書即某個實體的身份證明,直接代表着實體本身參與資訊交流活動。Citadel作為證書分發中心,負責替服務網格中每個服務建立身份證書,友善服務之間安全交流。

這個問題的現象是,Citadel再也無法啟動了,導緻無法建立新的虛拟服務和Pod執行個體。觀察Citadel,發現其不斷重新開機,并輸出以下報錯資訊。

2019-11-22T02:40:34.814547Z warn Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.

2019-11-22T02:40:34.815408Z info Use self-signed certificate as the CA certificate

2019-11-22T02:40:34.840128Z error Failed to create a self-signed Citadel (error: [failed to create CA KeyCertBundle (cannot verify the cert with the provided root chain and cert pool)])

通過代碼分析,以及最後一行報錯,可以了解問題背後的邏輯:

1.Citadel不能啟動,是因為其無法建立自簽名的證書(Failed to create a self-signed Citadel)

2.Citadel無法建立自簽名證書的原因,又是由于它不能建立秘鑰和證書(failed to create CA KeyCertBundle)

3.而前兩條的根本的原因,是因為在驗證建立的自簽名證書的時候,驗證失敗(cannot verify the cert with the provided root chain and cert pool)

一般意義上的證書驗證

證書的簽發關系,會把證書連接配接成一棵證書簽發關系樹。頂部是根證書,一般由可信第三方持有,根證書都是自簽名的,即其不需要其他機構來對其身份提供證明。其他層級的CA憑證,都是由上一層CA憑證簽發。最底層的證書,是給具體應用使用的證書。

驗證這棵樹上的證書,分兩種情況:

根證書驗證。因為即是簽發者,又是被簽發者,是以根證書驗證,隻需要提供根證書本身,一般肯定驗證成功。

其他證書驗證。需要提供證書本身,以及其上層所有CA憑證,包括根證書。

自簽名證書驗證失敗Citadel啟動失敗的根本原因,是其建立的自簽名的證書,無法驗證通過。而這一點,也是我處理問題時,卡殼的原因。左思右想,不明白為什麼剛剛建立的自簽名證書,都驗證不通過。

大神定理

有一條定理,就是我們絞盡腦汁,耗費大量時間無法解決的問題,在大神眼裡,可能就是幾秒鐘的事情。11月22号半夜,這條真理再次被驗證。

因為實在想不通,但是使用者又非常着急,是以最終還是打擾了一位大神,他隻大概看了一下報錯,就判斷是CA憑證過期問題。使用istio提供的證書驗證腳本,很快證明了他的判斷。相關文章見最後參考部分。

Citadel證書體系

問題解決了,這裡總結下Citadel證書體系。大多數使用者使用Isito的時候,都會選擇使用自簽名的根證書。自簽名根證書,證書,以及證書使用者sidecar三種之間有三種關系:

1.根證書和證書之間的簽發關系。這種關系,保證了信任的傳遞性質。

2.證書和sidecar之間的持有和被持有關系。某種意義上,這是給pod/sidecar和證書畫上了等号。

3.根證書和sidecar之間的信任關系。這與前兩條加起來,sidecar就信任所有根證書簽發的證書。

以上三條,即可保證,在互相通信的時候,pod/sidecar之間可以完成tls雙向認證成功。

犯的錯

這個問題排查中,實際上犯了兩個錯誤。一個是代碼閱讀不仔細,一直盯着自簽名證書建立的邏輯看。因為有了這個前提,即建立證書驗證失敗,是以沒有辦法了解,為什麼建立的自簽名證書也會驗證失敗,是以傾向于認為是底層安全庫出了問題;另外一個是,隻盯着Citadel不能啟動的報錯做,忽略了另外一條線索,就是Pod和虛拟服務建立失敗。實際上後來發現,pod和虛拟服務建立失敗的報錯,有更明顯的證書過期錯誤資訊。

virtualservices.networking.istio.io "xxxx" could not be patched: Internal error occurred: failed calling admission webhook "pilot.validation.istio.io": Post https://istio-galley.istio-system.svc:443/admitpilot?timeout=30s: x509: certificate has expired or is not yet valid.

後記

在Istio比較早期的版本中,自簽名Ca證書有效期隻有一年時間,如果使用老版本Istio超過一年,就會遇到這個問題。當證書過期之後,我們建立新的虛拟服務或者pod,都會因為CA憑證過期而失敗。而這時如果Citadel重新開機,它會讀取過期證書并驗證其有效性,就會出現以上Cidatel不能啟動的問題。

這個Ca證書在K8s叢集中,是以istio-ca-secret命名的secret,我們可以使用openssl解碼證書來檢視有效期。這個問題比較簡單的處理方法,就是删除這個Secret,并重新開機Citadel,這時Citadel會走向建立和驗證自簽名Ca證書的邏輯并重新整理Ca證書。或者參考以下官網處理方式。

參考

https://istio.io/docs/ops/security/root-transition/

繼續閱讀