在阿里巴巴,我們如何先於使用者發現和定位 Kubernetes 叢集問題?
簡介:本文整理自阿里雲高階研發工程師彭南光(光南) 在 KubeCon China 2021 大會的演講實錄,分享了阿里巴巴是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對大規模叢集的穩定性挑戰的。關於阿里云云原生團隊在本次 KubeCon 上分享的全部內容沉澱於電子書《雲原生與雲未來的新可能》當中,可點選文末“閱讀原文”下載。
作者:彭南光(光南)
本文整理自阿里雲高階研發工程師彭南光(光南) 在 KubeCon China 2021 大會的演講實錄,分享了阿里巴巴是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對大規模叢集的穩定性挑戰的。關於阿里云云原生團隊在本次 KubeCon 上分享的全部內容沉澱於電子書《雲原生與雲未來的新可能》當中,可點選文末“閱讀原文”下載。
快速發現和定位問題的能力是快速恢復系統的基石,只有先做到快速發現和定位問題,才能談如何解決問題,儘量減少使用者損失。那麼如何在複雜的大規模場景中,做到真正的先於使用者發現和定位問題呢?我會將我們在管理大型 Kubernetes 叢集過程中快速發現和定位問題的一些經驗和實踐帶給大家——我們是如何通過自研通用鏈路探測+定向巡檢工具 KubeProbe 應對遇到的大規模叢集的穩定性挑戰的。
鏈路探測:模擬廣義使用者行為,探測鏈路和系統是否異常
定向檢測:檢查叢集異常指標,發現未來存在或可能存在的風險點
系統增強:發現問題提速增效,根因分析
發現問題之後:後置檢查和自愈,Chat-Ops
業務背景和挑戰
阿里云云原生應用平臺的容器服務團隊,擁有 ACK 、ASI 等產品,管理了大規模的 Kubernetes 叢集,不僅向外部公有云使用者提供 Kubernetes 服務,還承擔了阿里巴巴集團上雲,阿里巴巴應用全面容器化的工作。
目前,整個阿里巴巴的業務都跑在 Kubernetes 叢集上並實現了雲原生和容器化,例如:天貓/淘寶/高德/考拉/餓了麼等等。容器服務作為阿里雲的管控底座,各種雲服務也執行在這些叢集之上,例如視訊雲/dataworks /MSE 微服務引擎/MQ 訊息佇列等等。我們需要對這些基礎設施的穩定性負責。
現在,雲原生的架構越來越流行,越來越多的產品和應用開始選擇雲原生架構,這裡有一張圖,大致示意了現代的雲原生應用架構,應用生於雲上,長於雲上,各級提供分層的服務,這種分層的服務能夠讓業務和應用專注於業務層,遮蔽平臺和基礎設施層的複雜概念。
很多時候,好的應用開發者不一定是基礎設施專家,雲原生讓業務專注業務,基礎設施專注基礎設施。同時,業務很多時候也只能關心業務自身的穩定性,業務大多數時候沒有能力關心,或者是不希望投入大量的人力關心基礎設施和平臺層的穩定性,所以,關於平臺層和基礎設施的穩定性問題上,我們需要把複雜留給自己,把簡單留給使用者,為使用者提供穩定的平臺層服務。同時,更加關心全域性穩定性和全域性的可用性,而不是單點可用性。
因此元件的繁雜、變更頻繁、使用者場景各異、叢集規模龐大、業務架構複雜……都給業務帶來了挑戰:
挑戰一:如何降低系統風險。場景複雜,業務形態各異,任何一個不起眼細節的遺漏或環節的處置不慎都有可能導致傷害的擴大化;
挑戰二:如何對使用者叢集的穩定性負責。如何先於使用者發現和定位問題成為容器服務生產穩定性建設的重中之重,也是全域性高可用體系的基石。
系統是如此的複雜,任何一個不起眼的細節遺漏或處理不慎都有可能導致非預期的傷害,我們要怎樣才能降低系統風險呢?另外我們又是如何對形態各異的使用者叢集執行時全域性穩定性負責的呢?如何才能先於使用者發現和定位這些叢集中已經存在或即將發生的問題,是保障叢集的穩定性建設的重中之重,也是 Kubernetes 全域性高可用體系的基石。
思考和方案
基於這些挑戰,我們做了一些思考和預設。下圖是一個極度簡化的使用者釋出擴容鏈路,雖說極度簡化,但實際我們仍可以看出,鏈路還是比較複雜的。
為了保障這次使用者的擴容/釋出鏈路暢通,我們首先帶來幾個預設:
預設 2:即使鏈路中各元件/節點監控資料正常,也不能保證叢集整體鏈路 100% 可用,只有經過實際業務全鏈路探測才能確定實際可用的結論;
預設 3:反證法在證明叢集不可用場景一定優於舉證法,即使 100% 監控資料正常,但只要釋出失敗則證明鏈路不通。 另外,在單叢集之外,我們還要關注多叢集的管理,下面是一些多叢集管控中的不穩定性因素示例,可以看到,多叢集場景下,穩定性管控的複雜度會被放大,我們繼續帶來幾個預設:
預設 4:在大規模叢集場景下資料一致性的問題會愈加顯現,並且可能引發嚴重故障,成為一個顯著的不穩定因素;
預設 5:叢集內的監控告警鏈路存在自依賴風險,如果叢集故障,則監控告警也有可能同時故障。
探索和解決方案
1. 鏈路探測
鏈路探測即模擬廣義上的使用者行為,探測鏈路是否暢通,流程是否無異常。
所謂鏈路探測,就是模擬廣義上的使用者行為,去對叢集元件鏈路中的各種等待探測的物件去做探測。此處要特別說明的是,這裡的使用者並不僅僅指的是狹義上使用系統的同學,而是更廣義的使用者,或者可以理解和引申成為依賴下游。
另外,在實現全鏈路探測的同時,拆解電路,實現全電路中的短路探測也是非常必要的,也是對全鏈路探測的一個補充。
2. 定向巡檢
定向巡檢是指檢查和分析大規模叢集的異常指標,找到已有或將來可能存在的風險點,就像檢修管道一樣。
接下來是關於鏈路探測的一些常見場景:
另外,所謂鏈路探測,就是讓自己成為自己系統的使用者,模擬廣義上的“使用者”行為去對叢集/元件/鏈路裡的各種等待探測的物件去做探測。
一定要注意,這裡的“使用者”並不僅僅指的是狹義上使用系統的同學,而是更廣義的使用者,或者可以理解引申為依賴下游。
例如業務同學要釋出業務,就必然要經過 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,最終因為功能上不太適用於我們的場景,我們選擇了自研自建。
我舉一個例子,比如 Kubelet 在我們的元件運維平臺上做分批發布,每批次都會觸發一次相關叢集的鏈路探測用例作為後置檢查,一旦我們發現某次釋出的後置檢查失敗,我們會阻斷掉使用者的當前釋出,防止傷害擴大,同時第一時間告警以及通知相關同事進入排查,是否元件新版本不符合預期。
同時,我們也支援第三方的事件回撥,可以更快的整合進三方系統中。
另外,我們對於某些需要 7*24 小時不間斷的高頻次短週期探測用例,我們還實現了另外一套常駐分散式架構,這套架構使用一個叢集內的 ProbeOperator 監聽 Probe Config CRD 變化,在探測 pod 中周而復始的執行探測邏輯。這套架構,完美複用了 KubeProbe 中心端提供的告警/根因分析/釋出阻斷等等附加功能,同時使用了標準 Operator 的雲原生架構設計,常駐體系帶來了極大的探測頻率提升(因為去掉了建立巡檢 pod 和清理資料的開銷)基本可以做到對叢集的 7*24 小時無縫覆蓋,同時便於對外整合。
從我們的實踐上來說,測試同學和業務同學貢獻了很多相關的檢查用例,比如測試同學貢獻的 ACK & ASK 的建立刪除全鏈路探測巡檢,金絲雀業務全鏈路擴容用例,比如本地生活同學的 PaaS 平臺應用檢查等等,也得到了很多穩定性上的結果和收益。目前我們維護的巡檢/探測用例有數十個,明年有機會破百,巡檢/探測次數近 3000 萬次,明年可能會過億。目前可以提前發現 99%以上的叢集管控問題和隱患,效果是非常好的。
發現問題之後:根因分析和事件處理
接下來我們聊聊發現問題之後的事情,這裡有一個類似於問診對話的例子,患者發現 “哎呀我不舒服了!”這就是發現問題。醫生參考各種化驗單,同時做了資訊聚合分析推斷,告訴患者“你已經 24 小時沒睡覺了,你睡不著是因為你很焦慮,你焦慮的根因是因為後天就要期末考試了。”這便是定位問題根因,然後針對根因去解決這個問題,他告訴患者“不要擔心,我剛收到的訊息,小學生已經不需要期末考試了。”這個過程一定要快!
另外快速定位問題和根因分析,是一個樹狀的搜尋,經驗加工判斷的過程,也就是如何從一個混沌的表象推斷出根因,核心是邏輯。
這和健康體檢是不同的,健康體檢是列出檢查項 1,2,3,4,5......然後告訴你一堆數值。很多時候,即使存在體檢中心,我們仍然也需要醫院的專業醫生來為您解讀和判斷病情,不是嗎?
同時,根因分析/問題自愈的關鍵在於專家經驗的下沉,也就是把專家經驗下沉到系統中去,專家經驗的下沉帶來的最大收益是可複用可輸出。你可以想一下,如果我們把一個最專業的醫生的能力放進系統裡,他是不是更方便的為每一個人分析病情呢?
此外我再補充一點,文字聯想也是一個很好的根因分析方式,我們可以通過機器學習訓練文字識別的方式來聯想出和這種失敗 case 最關聯的根因,這種 AIOps 的工作我們只是略微涉及,還在持續的探索中,我們的資料量非常大,我認為這一定是未來的方向之一。
上圖的左下方是某次我們失敗的告警,它經過根因分析系統之後發現首先最核心,最關聯,最大的原因可能是 APIserver 的連線斷開並且當前已經恢復,所以可能只是偶發的網路抖動,我們暫時不用特別關注,但此時可以看到置信度為 90%。
另外還有一些可能的原因都會關聯起來。比如某個元件,這次探測它是由某一個元件釋出出發的,它的釋出人是 XXX,我們可以觀察這個釋出對 API server 會產生某些影響,是否多次 list watch 不符合預期,然後把 API server list watch 出問題了,置信度有 50%。
當我們得到一個初步的原因之後,我們會進入二次確認系統做二次的原因確認,比如我們判斷原因可能是 APIServer 超時/etcd 斷聯/節點超時等,我們就會自動重新拉取一下 APIServer 介面,看一下此時是否仍然超時,是否恢復,如果恢復了,我們就普通告警,並且告訴使用者,現在沒事了,但是你得關注。如果沒恢復,那這就很嚴重了,屬於最高優先順序,直接電話告警。
就是這個思路,如果有系統無法定位的問題,並且持續無法定位,我們也會觸發高級別告警,並且會增加相關的根因分析識別樹邏輯。
過多的告警等於沒有告警,我是最討厭告警海的。從經驗上講,當我們構建了一套這樣的根因分析+二次確認+後置檢查系統之後,我們的 Oncall 成本下降了 90% 以上,並且還能夠持續下降,終態可以說是無人值守,大家也可以試試類似的工作,可以說是投入小,見效大。自從這些系統建設起來以後,我們可以自豪的說,我們用很小的精力 Oncall 了每一個告警條目(對,是每一條告警,是數千個叢集,數千萬次探測巡檢的每一條告警)並且不會有任何遺漏了。
最後是一些給 Oncall 人員的小甜品,Chat-ops。
我們利用釘釘提供的 NLP 機器人,構建了一套比較完善的 Chat-ops 系統,這樣之後我們的 Oncall 人員就可以很方便的在告警群裡通過聊天的方式操作 KubeProbe 相關功能了,比如:重跑失敗探測,查詢叢集狀態,拉取診斷資訊,查詢探測日誌,叢集告警靜默。
比如晚上我已經再被窩裡了,這時候它給我了一個告警,比如某個叢集之前出現了某次失敗但當前已經恢復了,需要我關注一下。
既然我關注了,我便希望某一個常用例再跑一次(它可能週期比較長,例如一個鐘頭),由於短鏈路的用例可能隨時都在跑,此時我便告訴機器人再跑一次,機器人就會識別我的語義,將叢集再跑一次。跑完之後,我再通過查詢狀態看一下這個叢集當前的狀態怎麼樣了,這樣是非常方便的,有時候你晚上上班了,或者是在路上,或者是在被窩裡,都也可以很舒服的去 on-call 一個系統了。
Demo 示例
1、釋出
本文為阿里雲原創內容,未經允許不得轉載。