1. 程式人生 > 其它 >在阿里巴巴,我們如何先於使用者發現和定位 Kubernetes 叢集問題?

在阿里巴巴,我們如何先於使用者發現和定位 Kubernetes 叢集問題?

簡介:本文整理自阿里雲高階研發工程師彭南光(光南) 在 KubeCon China 2021 大會的演講實錄,分享了阿里巴巴是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對大規模叢集的穩定性挑戰的。關於阿里云云原生團隊在本次 KubeCon 上分享的全部內容沉澱於電子書《雲原生與雲未來的新可能》當中,可點選文末“閱讀原文”下載。

作者:彭南光(光南)

本文整理自阿里雲高階研發工程師彭南光(光南) 在 KubeCon China 2021 大會的演講實錄,分享了阿里巴巴是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對大規模叢集的穩定性挑戰的。關於阿里云云原生團隊在本次 KubeCon 上分享的全部內容沉澱於電子書《雲原生與雲未來的新可能》當中,可點選文末“閱讀原文”下載。

快速發現和定位問題的能力是快速恢復系統的基石,只有先做到快速發現和定位問題,才能談如何解決問題,儘量減少使用者損失。那麼如何在複雜的大規模場景中,做到真正的先於使用者發現和定位問題呢?我會將我們在管理大型 Kubernetes 叢集過程中快速發現和定位問題的一些經驗和實踐帶給大家——我們是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對遇到的大規模叢集的穩定性挑戰的。 

鏈路探測:模擬廣義使用者行為,探測鏈路和系統是否異常

定向檢測:檢查叢集異常指標,發現未來存在或可能存在的風險點

系統增強:發現問題提速增效,根因分析

發現問題之後:後置檢查和自愈,Chat-Ops 

業務背景和挑戰

阿里云云原生應用平臺的容器服務團隊,擁有 ACK 、ASI 等產品,管理了大規模的 Kubernetes 叢集,不僅向外部公有云使用者提供 Kubernetes 服務,還承擔了阿里巴巴集團上雲,阿里巴巴應用全面容器化的工作。

目前,整個阿里巴巴的業務都跑在 Kubernetes 叢集上並實現了雲原生和容器化,例如:天貓/淘寶/高德/考拉/餓了麼等等。容器服務作為阿里雲的管控底座,各種雲服務也執行在這些叢集之上,例如視訊雲/dataworks /MSE 微服務引擎/MQ 訊息佇列等等。我們需要對這些基礎設施的穩定性負責。

 現在,雲原生的架構越來越流行,越來越多的產品和應用開始選擇雲原生架構,這裡有一張圖,大致示意了現代的雲原生應用架構,應用生於雲上,長於雲上,各級提供分層的服務,這種分層的服務能夠讓業務和應用專注於業務層,遮蔽平臺和基礎設施層的複雜概念。

從穩定性的角度來講,這種應用的架構分層,上層應用的穩定性就會開始依賴底層基礎設施的支援;另外,大一統的基座既為大規模的資源排程優化和在離線混部提供場景,也對基礎設施團隊維護大規模叢集的穩定性問題提出極大的挑戰。

這裡有兩張形象的圖示可以展現出雲原生應用架構下的業務應用和平臺層基礎設施的關係,Kubernetes 叢集是非常複雜的,一個單叢集的鏈路元件就有數十個甚至上百個之多,何況是大規模的多叢集管理呢?但執行在上層的業務同學並不會感知到複雜,因為我們已經把複雜包掉了,留給使用者的是一個簡單的統一介面。就像淘寶這樣的應用其實是非常複雜的,但在使用者看來只是一個簡單的提交訂單而已,按鍵背後蘊含著極其複雜的內容。為什麼做到這樣?因為我們把複雜留給了自己,把簡單交給了使用者。 

很多時候,好的應用開發者不一定是基礎設施專家,雲原生讓業務專注業務,基礎設施專注基礎設施。同時,業務很多時候也只能關心業務自身的穩定性,業務大多數時候沒有能力關心,或者是不希望投入大量的人力關心基礎設施和平臺層的穩定性,所以,關於平臺層和基礎設施的穩定性問題上,我們需要把複雜留給自己,把簡單留給使用者,為使用者提供穩定的平臺層服務。同時,更加關心全域性穩定性和全域性的可用性,而不是單點可用性。

容器服務是阿里巴巴集團業務以及阿里雲管控/雲服務的底座,上面跑著各種各樣的業務,如電商業務/中介軟體/二方業務/搜尋/阿里云云服務等等。此外還有數百個自研和開源的元件,每年數十萬次的元件變更/數千個叢集/數十萬臺節點,甚至大的叢集單叢集節點規模已過萬。業務架構更是紛繁複雜,有單租叢集、多租叢集、vc 叢集、聯邦叢集等等,同時還有各種在離線混布、統一排程、大促活動。在執行時也存在多種形態,如 runC,runD 等等。

因此元件的繁雜、變更頻繁、使用者場景各異、叢集規模龐大、業務架構複雜……都給業務帶來了挑戰:

挑戰一:如何降低系統風險。場景複雜,業務形態各異,任何一個不起眼細節的遺漏或環節的處置不慎都有可能導致傷害的擴大化;

挑戰二:如何對使用者叢集的穩定性負責。如何先於使用者發現和定位問題成為容器服務生產穩定性建設的重中之重,也是全域性高可用體系的基石。 

系統是如此的複雜,任何一個不起眼的細節遺漏或處理不慎都有可能導致非預期的傷害,我們要怎樣才能降低系統風險呢?另外我們又是如何對形態各異的使用者叢集執行時全域性穩定性負責的呢?如何才能先於使用者發現和定位這些叢集中已經存在或即將發生的問題,是保障叢集的穩定性建設的重中之重,也是 Kubernetes 全域性高可用體系的基石。

思考和方案

基於這些挑戰,我們做了一些思考和預設。下圖是一個極度簡化的使用者釋出擴容鏈路,雖說極度簡化,但實際我們仍可以看出,鏈路還是比較複雜的。

為了保障這次使用者的擴容/釋出鏈路暢通,我們首先帶來幾個預設:

預設 1:鏈路複雜元件眾多,各元件分別升級迭代,資料監控無法無死角覆蓋全部場景;

預設 2:即使鏈路中各元件/節點監控資料正常,也不能保證叢集整體鏈路 100% 可用,只有經過實際業務全鏈路探測才能確定實際可用的結論;

預設 3:反證法在證明叢集不可用場景一定優於舉證法,即使 100% 監控資料正常,但只要釋出失敗則證明鏈路不通。 另外,在單叢集之外,我們還要關注多叢集的管理,下面是一些多叢集管控中的不穩定性因素示例,可以看到,多叢集場景下,穩定性管控的複雜度會被放大,我們繼續帶來幾個預設:

預設 4:在大規模叢集場景下資料一致性的問題會愈加顯現,並且可能引發嚴重故障,成為一個顯著的不穩定因素;

預設 5:叢集內的監控告警鏈路存在自依賴風險,如果叢集故障,則監控告警也有可能同時故障。

接下來是我們基於以上預設的一些解決方案。

探索和解決方案

1.  鏈路探測

鏈路探測即模擬廣義上的使用者行為,探測鏈路是否暢通,流程是否無異常。

想要做到先於使用者發現系統問題,我們自己首先要成為系統使用者,並且是使用最多、瞭解最深、無時無刻不在使用和感知系統狀態的使用者。

所謂鏈路探測,就是模擬廣義上的使用者行為,去對叢集元件鏈路中的各種等待探測的物件去做探測。此處要特別說明的是,這裡的使用者並不僅僅指的是狹義上使用系統的同學,而是更廣義的使用者,或者可以理解和引申成為依賴下游。

另外,在實現全鏈路探測的同時,拆解電路,實現全電路中的短路探測也是非常必要的,也是對全鏈路探測的一個補充。

2.  定向巡檢

定向巡檢是指檢查和分析大規模叢集的異常指標,找到已有或將來可能存在的風險點,就像檢修管道一樣。

例如有若干個叢集,它分為很多叢集組,不同叢集組之間的 etcd 冷/熱備是否配置齊備,風控限流配置是否正常,webhook 版本是否正常,混部引數是否一致,包括它的證書有效期是不是快要到期了等等。不同的叢集組之間可能有所差別,但同類型叢集之間是有一個轉衡的,因此我們可以定向做一些巡檢。 

接下來是關於鏈路探測的一些常見場景: 

就像一個遊戲策劃,如果他連自己製作的遊戲都不玩,他可能發現遊戲機制的問題,把這個遊戲越做越好嗎?我們要做到先於使用者發現系統問題,那我們自己首先就要先成為系統的使用者,並且一定是使用最多的,瞭解最深的,無時無刻不在使用和感知系統狀態的使用者。 

另外,所謂鏈路探測,就是讓自己成為自己系統的使用者,模擬廣義上的“使用者”行為去對叢集/元件/鏈路裡的各種等待探測的物件去做探測。 

一定要注意,這裡的“使用者”並不僅僅指的是狹義上使用系統的同學,而是更廣義的使用者,或者可以理解引申為依賴下游。 

例如業務同學要釋出業務,就必然要經過 git 系統,再到釋出系統,再到我們底層的基礎設施平臺,也就是我們的 ASI,這就是一次全鏈路探測流程。在這裡業務同學就是使用者,探測物件可以是全鏈路。 但如果我們把 etcd 看作一個系統服務,那麼 APIServer 就是它廣義上的使用者,我們模擬 APIServer 請求 etcd 這條鏈路的探測也就有了意義。 

另外像 MSE 操作 zookeeper,外部使用者通過阿里雲控制檯建立 ACK 叢集,PaaS 平臺操作聯邦叢集,甚至視訊雲業務方發起一次轉碼任務,都是一樣的道理。

還有一點要關注的就是,雖然全鏈路探測看起來很美,但很多時候,全鏈路探測同時還很長,可能等到失敗的時候問題已經很大了。所以,在實現全鏈路探測的同時,拆解鏈路,實現全鏈路中的短鏈路探測也是非常必要的,也是對全鏈路探測的一個補充。 

上圖是定向巡檢的場景,相比鏈路探測關注於鏈路可用性,定向巡檢的核心還是在大規模的叢集場景下,資料一致性是非常困難的問題,資料不一致,將導致一些隱患,可能會在未來引發某些不確定性的故障。 

所謂定向巡檢就是對整個叢集或鏈路中的各項資料、指標做已知原因的檢查,找出不一致或資料偏離的點,判斷是否可能引發風險,從而做到防患於未然,治未病。

比如我們這個裡邊有同一種類型的叢集組,A 叢集發現它的證書有效期不到三年,而其他叢集的證書有效期都有三年;B 叢集的 webhook 版本可能是 v2,而其他叢集的 webhook 版本是 v3;C 叢集的風控限流配置並沒有配一個驅逐 Pod 的限流,但其他叢集都配配置了驅逐 Pod 的限流,這肯定是不符合預期的;再比如 D 叢集的 etcd 的冷/熱備沒有配置或者是執行不正常,我們也可以先把它檢查出來。

系統實現

基於上面許許多多的背景預設以及方案,我們設計並實現了一套巡檢/探測平臺,我們取名為 KubeProbe (並未開源,和現在社群上有類似命名的專案沒有任何聯絡)。

我們早期也曾考慮使用社群專案 Kuberhealthy,併為 Kuberhealthy 做過一些程式碼貢獻,修復過一些嚴重的程式碼 Bug,最終因為功能上不太適用於我們的場景,我們選擇了自研自建。

上圖是一套中心架構,我們會有一套中心管控系統。使用者的用例會通過統一倉庫的映象的方式接入,使用我們通用的 sdk 庫,自定義巡檢和探測邏輯。我們會在中心管控系統上配置好叢集和用例的關係配置,如某用例應該執行在哪些叢集組上,並做好各種執行時配置。我們支援了週期觸發/手動觸發/事件觸發(如釋出)的用例觸發方式。用例觸發後會在叢集內建立一個執行巡檢/探測邏輯的 Pod,這個 Pod 裡會執行各種使用者自定義的業務巡檢/探測邏輯,並在成功和失敗後通過直接回調/訊息佇列的方式通知中心端。中心端會負責告警和用例資源清理的工作。 

我舉一個例子,比如 Kubelet 在我們的元件運維平臺上做分批發布,每批次都會觸發一次相關叢集的鏈路探測用例作為後置檢查,一旦我們發現某次釋出的後置檢查失敗,我們會阻斷掉使用者的當前釋出,防止傷害擴大,同時第一時間告警以及通知相關同事進入排查,是否元件新版本不符合預期。 

同時,我們也支援第三方的事件回撥,可以更快的整合進三方系統中。 

另外,我們對於某些需要 7*24 小時不間斷的高頻次短週期探測用例,我們還實現了另外一套常駐分散式架構,這套架構使用一個叢集內的 ProbeOperator 監聽 Probe Config CRD 變化,在探測 pod 中周而復始的執行探測邏輯。這套架構,完美複用了 KubeProbe 中心端提供的告警/根因分析/釋出阻斷等等附加功能,同時使用了標準  Operator 的雲原生架構設計,常駐體系帶來了極大的探測頻率提升(因為去掉了建立巡檢 pod 和清理資料的開銷)基本可以做到對叢集的 7*24 小時無縫覆蓋,同時便於對外整合。 

另外還有一個必須要提的非常重要的點,即平臺只是提供了一個平臺層的能力支援,真正這個東西要起作用,還是要看在這個平臺上構建的用例是否豐富,能不能方便的讓更多人進來寫各種巡檢和探測用例。就像測試平臺很重要,但測試用例比測試平臺更重要這個道理一樣。一些通用的 workload 探測,元件探測,固然能發現很多管控鏈路上的問題,但是更多的問題,甚至業務層的問題暴露,實際上依賴於基礎設施和業務層同學的共同努力。 

從我們的實踐上來說,測試同學和業務同學貢獻了很多相關的檢查用例,比如測試同學貢獻的 ACK & ASK 的建立刪除全鏈路探測巡檢,金絲雀業務全鏈路擴容用例,比如本地生活同學的 PaaS 平臺應用檢查等等,也得到了很多穩定性上的結果和收益。目前我們維護的巡檢/探測用例有數十個,明年有機會破百,巡檢/探測次數近 3000 萬次,明年可能會過億。目前可以提前發現 99%以上的叢集管控問題和隱患,效果是非常好的。

發現問題之後:根因分析和事件處理

接下來我們聊聊發現問題之後的事情,這裡有一個類似於問診對話的例子,患者發現 “哎呀我不舒服了!”這就是發現問題。醫生參考各種化驗單,同時做了資訊聚合分析推斷,告訴患者“你已經 24 小時沒睡覺了,你睡不著是因為你很焦慮,你焦慮的根因是因為後天就要期末考試了。”這便是定位問題根因,然後針對根因去解決這個問題,他告訴患者“不要擔心,我剛收到的訊息,小學生已經不需要期末考試了。”這個過程一定要快! 

來自探測鏈路的告警內容往往是混沌的,和資料監控告警是有所差異的。就像上文提到的,鏈路探測告警的告警很可能就是一句患者的我不舒服了,需要你作為醫生去判斷,為什麼他不舒服了呢?根因是什麼。而資料監控很多時候本身就代表了原因,比如 Etcd OOM,用已有的 oncall 經驗可能得不到最好的效果。 

另外快速定位問題和根因分析,是一個樹狀的搜尋,經驗加工判斷的過程,也就是如何從一個混沌的表象推斷出根因,核心是邏輯。 

這和健康體檢是不同的,健康體檢是列出檢查項 1,2,3,4,5......然後告訴你一堆數值。很多時候,即使存在體檢中心,我們仍然也需要醫院的專業醫生來為您解讀和判斷病情,不是嗎? 

同時,根因分析/問題自愈的關鍵在於專家經驗的下沉,也就是把專家經驗下沉到系統中去,專家經驗的下沉帶來的最大收益是可複用可輸出。你可以想一下,如果我們把一個最專業的醫生的能力放進系統裡,他是不是更方便的為每一個人分析病情呢? 

這便是 KubeProbe 發現問題之後的全流程,我們首先會經過一個我們自建的中心化根因分析系統,在這裡我們會聚合分析所有和本次失敗相關的資訊,包括事件/日誌/變更/告警/元件升級等等,我們將這些資訊進行聚合分析,並對事件做關聯處理,最終通過一個樹狀的分析系統初步定位出某次探測失敗的原因,比如說 APIServer 超時或者 etcd 斷連等等。 

此外我再補充一點,文字聯想也是一個很好的根因分析方式,我們可以通過機器學習訓練文字識別的方式來聯想出和這種失敗 case 最關聯的根因,這種 AIOps 的工作我們只是略微涉及,還在持續的探索中,我們的資料量非常大,我認為這一定是未來的方向之一。

KubeProbe 根因分析和後置處理全流程

上圖的左下方是某次我們失敗的告警,它經過根因分析系統之後發現首先最核心,最關聯,最大的原因可能是 APIserver 的連線斷開並且當前已經恢復,所以可能只是偶發的網路抖動,我們暫時不用特別關注,但此時可以看到置信度為 90%。 

另外還有一些可能的原因都會關聯起來。比如某個元件,這次探測它是由某一個元件釋出出發的,它的釋出人是 XXX,我們可以觀察這個釋出對 API server 會產生某些影響,是否多次 list watch 不符合預期,然後把 API server list watch 出問題了,置信度有 50%。 

當我們得到一個初步的原因之後,我們會進入二次確認系統做二次的原因確認,比如我們判斷原因可能是 APIServer 超時/etcd 斷聯/節點超時等,我們就會自動重新拉取一下 APIServer 介面,看一下此時是否仍然超時,是否恢復,如果恢復了,我們就普通告警,並且告訴使用者,現在沒事了,但是你得關注。如果沒恢復,那這就很嚴重了,屬於最高優先順序,直接電話告警。 

就是這個思路,如果有系統無法定位的問題,並且持續無法定位,我們也會觸發高級別告警,並且會增加相關的根因分析識別樹邏輯。 

過多的告警等於沒有告警,我是最討厭告警海的。從經驗上講,當我們構建了一套這樣的根因分析+二次確認+後置檢查系統之後,我們的 Oncall 成本下降了 90% 以上,並且還能夠持續下降,終態可以說是無人值守,大家也可以試試類似的工作,可以說是投入小,見效大。自從這些系統建設起來以後,我們可以自豪的說,我們用很小的精力 Oncall 了每一個告警條目(對,是每一條告警,是數千個叢集,數千萬次探測巡檢的每一條告警)並且不會有任何遺漏了。 

最後是一些給 Oncall 人員的小甜品,Chat-ops。 

基於 NLP 語義識別的 Chat-ops 系統 

我們利用釘釘提供的 NLP 機器人,構建了一套比較完善的 Chat-ops 系統,這樣之後我們的 Oncall 人員就可以很方便的在告警群裡通過聊天的方式操作 KubeProbe 相關功能了,比如:重跑失敗探測,查詢叢集狀態,拉取診斷資訊,查詢探測日誌,叢集告警靜默。

上圖是我們操作 Chat-ops 系統的過程。這個過程非常方便。

比如晚上我已經再被窩裡了,這時候它給我了一個告警,比如某個叢集之前出現了某次失敗但當前已經恢復了,需要我關注一下。 

既然我關注了,我便希望某一個常用例再跑一次(它可能週期比較長,例如一個鐘頭),由於短鏈路的用例可能隨時都在跑,此時我便告訴機器人再跑一次,機器人就會識別我的語義,將叢集再跑一次。跑完之後,我再通過查詢狀態看一下這個叢集當前的狀態怎麼樣了,這樣是非常方便的,有時候你晚上上班了,或者是在路上,或者是在被窩裡,都也可以很舒服的去 on-call 一個系統了。

Demo 示例

1、釋出

2、探測列表

3、探測 Pod 開始執行

4、探測結果

5、根因分析&告警

6、Chat-ops

原文連結

本文為阿里雲原創內容,未經允許不得轉載。