您好,登錄后才能下訂單哦!
這篇文章給大家介紹在大規(guī)模 Kubernetes 集群上實現(xiàn)高 SLO 的方法是什么,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
Gartner 對 SLO 的定義:在 SLA 框架下,SLO 是系統(tǒng)必須要達到的目標;需要盡可能地保障調(diào)用方的成功。有些人可能會對 SLI/SLO/SLA 有困惑,可以先來看下三者的關(guān)系:
SLI 定義一個指標,來描述一個服務有多好算達到好的標準。比如 Pod 在 1min 內(nèi)交付。我們通常從遲延、可用性、吞吐率及成功率這些角度來制定 SLI。
SLO 定義了一個小目標,來衡量一個 SLI 指標在一段時間內(nèi)達到好的標準的比例。比如說,99% 的 Pod 在 1min 內(nèi)交付。當一項服務公布了其 SLO 的以后,用戶方就會對該服務的質(zhì)量有了期望。
**SLA **是 SLO 衍生出來的協(xié)議,常用于 SLO 定義的目標比例沒有完成時,服務方要賠多少錢。通常來說,SLA 的協(xié)議會具體白紙黑字形成有法律效率的合同,常用于服務供應商和外部客戶之間(例如阿里云和阿里云的使用者)。一般來說對于內(nèi)部服務之間的 SLO 被打破,通常不會是經(jīng)濟上的賠償,可能更多的是職責上的認定。
所以,我們在系統(tǒng)內(nèi)部更多關(guān)注的是 SLO。
隨著生產(chǎn)環(huán)境不斷發(fā)展、K8s 集群越來越復雜、集群規(guī)模不斷增大。如何保障大規(guī)模環(huán)境 K8s 集群的可用性?是擺在眾多廠家面前的一個難題。對于 K8s 集群,我們通常關(guān)心以下幾個問題:
第一個問題就是集群是否健康,所有組件是否正常工作,集群中 Pod 創(chuàng)建的失敗數(shù)量有多少,這是一個整體指標的問題。
第二個問題就是集群中發(fā)生了什么,集群中是否有異常發(fā)生了,用戶在集群中做了些什么事情,這是一個追蹤能力的問題。
第三個問題就是有了異常后,是哪個組件出了問題導致成功率降低,這是一個原因定位的問題。
那么,我們該如何解決上面的問題呢?
首先,我們要定義一套 SLO,來描述集群的可用性。
接著,我們必須有能力對集群中 Pod 的生命周期進行追蹤;對于失敗的 Pod,還需要分析出失敗原因,以快速定位異常組件。
最后,我們要通過優(yōu)化手段,消除集群的異常。
我們先來看下集群的一些指標。
第一項指標:集群健康度。目前有 Healthy/Warning/Fatal 三個值來描述,Warning 和 Fatal 對應著告警體系,比如 P2 告警發(fā)生,那集群就是 Warning;如果 P0 告警發(fā)生,那集群就是 Fatal,必須進行處理。
第二項指標:成功率。這里的成功率是指 Pod 的創(chuàng)建成功率。Pod 成功率是一個非常重要的指標,螞蟻一周 Pod 創(chuàng)建量是百萬級的,成功率的波動會造成大量 Pod 的失??;而且 Pod 成功率的下跌,是集群異常的最直觀反應。
第三項指標:殘留 Terminating Pod 的數(shù)量。為什么不用刪除成功率呢?因為在百萬級別的時候,即使 Pod 刪除成功率達到 99.9%,那么 Terminating Pod 的數(shù)量也是千級別的。殘留如此多的 Pod,會占著應用的容量,在生產(chǎn)環(huán)境中是不可接受的。
第四項指標:服務在線率。服務在線率是通過探針來衡量的,探針失敗,意味著集群不可用。服務在線率是會對 Master 組件來設計的。
最后一項指標:故障機數(shù)量,這是一個節(jié)點維度的指標。故障機通常是指那些無法正確交付 Pod 的物理機,可能是磁盤滿了,可能是 load 太高了。集群故障機并須做到“快速發(fā)現(xiàn),快速隔離,及時修復”,畢竟故障機會對集群容量造成影響。
有了集群的指標后,我們需要把這些指標進行細化,定義出成功的標準。
先來看 Pod 創(chuàng)建成功率指標。我們把 Pod 分為了普通 Pod 和 Job 類 Pob。普通 Pod 的 RestartPolicy 為 Always,Job 類 Pod 的 RestartPlicy 為 Never 或 OnFailure。兩者都設定有交付時間,比如必須在 1 分鐘以內(nèi)完成交付。普通 Pod 的交付標準是 1min 內(nèi) Pod 已經(jīng) Ready;Job 類 Pod 的交付標準是 1min 內(nèi) Pod 的狀態(tài)已達 Running、Succeeded 或 Failed。當然創(chuàng)建的時間需要把 PostStartHook 執(zhí)行時間排除。
對于 Pod 的刪除,成功的標準為:在規(guī)定時間內(nèi),Pod 從 ETCD 內(nèi)刪除。當然,刪除的時間需要把 PreStopHookPeriod 時間排除。
對于故障機,要盡快的發(fā)現(xiàn)并進行隔離和降級。比如物理機磁盤只讀,那必須在 1min 內(nèi)完成對該 Pod 打 taint。至于故障機的恢復時間,需要按不同的故障原因,制定不同的恢復時間。比如系統(tǒng)故障需要重要安裝系統(tǒng),那恢復時間就會長些。
有了這些標準后,我們也對 Pod 失敗的原因進行了整理,有些失敗原因是系統(tǒng)引起的,是我們需要關(guān)心的;有些失敗原因是用戶引發(fā)的,是我們不需要關(guān)心的。
比如 RuntimeError,就是一個系統(tǒng)錯誤,底層 Runtime 有問題了;ImagePullFailed,Kubelet 下載鏡像失敗,由于螞蟻有 Webhook 對鏡像準入做了校驗,所有鏡像下載失敗一般都是系統(tǒng)原因造成的。
對于用戶原因,在系統(tǒng)側(cè)無法解決,我們只把這些失敗原因以接口查詢的方式提供給用戶,讓用戶自己解決。比如 ContainerCrashLoopBackOff,通常是由用戶容器退出引起的。
圍繞 SLO 目標,我們構(gòu)建了一整套體系,一方面用于向終端用戶、運維人員展示當前集群各項指標狀;另一方面,各個組件相互協(xié)作,通過分析當前集群狀態(tài),得到影響 SLO 的各項因素,為提升集群 pod 交付成功率提供數(shù)據(jù)支持。
自頂向下而看,頂層組件主要面向各種指標數(shù)據(jù), 如集群健康狀態(tài)、pod 創(chuàng)建、刪除、升級成功率,殘留 pods 數(shù)量、不健康節(jié)點數(shù)量等指標。其中 Display Board 就是我們常說的監(jiān)控大盤。
我們同樣構(gòu)建了 Alert 告警子系統(tǒng),支持靈活的配置方式,可以為不同的指標,根據(jù)指標的下跌百分比,指標下跌絕對值等配置多種告警方式,如電話,短信,郵件等。
Analysis System 通過分析指標歷史數(shù)據(jù),以及采集到的節(jié)點 metrics 和 master 組件指標,給出更詳細的集群運營報告。其中:
Weekly Report 子系統(tǒng)給出當前集群本周 pod 創(chuàng)建/刪除/升級的數(shù)據(jù)統(tǒng)計,以及失敗案例原因匯總。
Terminating Pods Number 給出一段時間內(nèi)集群內(nèi)新增的無法通過 K8s 機制刪除的 pods 列表和 pods 殘留原因。
Unhealthy Nodes 則給出一個周期內(nèi)集群所有節(jié)點的總可用時間占比,每個節(jié)點的可用時間,運維記錄,以及不能自動恢復,需要人工介入恢復的節(jié)點列表。
為了支撐上述這些功能,我們開發(fā)了 Trace System,用來分析展示單個 pod 創(chuàng)建/刪除/升級失敗的具體原因。其中包含日志和事件采集、數(shù)據(jù)分析和 pod 生命周期展示三個模塊:
日志和事件采集模塊采集各 master 組件以及節(jié)點組件的運行日志和 pod/node 事件,分別以 pod/node 為索引存儲日志和事件。
數(shù)據(jù)分析模塊分析還原出 pod 生命周期中各階段用時,以及判斷 pod 失敗原因及節(jié)點不可用原因。
最后,由 Report 模塊向終端用戶暴露接口和 UI,向終端用戶展示 pod 生命周期以及出錯原因。
接下來,以一個 pod 創(chuàng)建失敗案例為例,向大家展示下 tracing 系統(tǒng)的工作流程。
用戶輸入 pod uid 之后,tracing system 通過 pod 索引,查找到 pod 對應生命周期分析記錄、交付成功與否判定結(jié)果。當然,storage 存儲的數(shù)據(jù)不僅為終端用戶提供基礎(chǔ)數(shù)據(jù),更重要的是通過對集群內(nèi) pods 生命周期,分析出周期內(nèi)集群的運營狀況及每個節(jié)點的運營狀況。比如說集群內(nèi)太多 pods 調(diào)度到熱點節(jié)點,不同 pods 的交付引起節(jié)點上資源競爭,導致節(jié)點負載太高,而交付能力卻在下降,最終表現(xiàn)為節(jié)點上 pods 交付超時。
再舉個例子,通過歷史統(tǒng)計數(shù)據(jù),分析出 pods 生命周期中各階段的執(zhí)行時間基線,以基線為評估標準,比較組件不同版本的平均用時、用時分布,給出組件改進建議。另外,通過整體的 pods 生命周期中各組件負責的步驟時間占比,找出占比較多的步驟,為后續(xù)優(yōu)化 pod 交付時間提供數(shù)據(jù)支持。
一個運行狀況良好的集群,不僅需要 master 組件保持高可用,節(jié)點穩(wěn)定性也不容忽視。
如果把 pod 創(chuàng)建比作是 rpc 調(diào)用,則每個節(jié)點就是一個 rpc 服務提供者,集群的總?cè)萘康扔诿總€節(jié)點能處理的 pod 創(chuàng)建請求的總和。每多一個不可用的節(jié)點,都代表著集群交付能力的下降,也代表著集群可用資源的下降,這就要求盡量保證集群內(nèi)節(jié)點高可用;每一次 pod 交付/刪除/升級失敗,也意味著用戶使用成本上升,體驗下降,這就要求集群節(jié)點只有保證良好的健康度,調(diào)度到節(jié)點上的 pods 才能成功交付。
換句話說,不僅要盡早發(fā)現(xiàn)節(jié)點異常,也要盡快修復節(jié)點。通過分析各組件在 pod 交付鏈路上的功能,我們補充了各種不同類型的組件的 metrics,以及將 host 運行狀態(tài)轉(zhuǎn)換為 metrics,一并采集到數(shù)據(jù)庫之后,結(jié)合每個節(jié)點上 pod 交付結(jié)果,可以構(gòu)建模型預測節(jié)點可用性,分析節(jié)點是否存在不可恢復異常,適當調(diào)整節(jié)點在調(diào)度器中比重,從而提升 pod 交付成功率。
Pod 創(chuàng)建/升級失敗,用戶可以通過重試來解決,但 pod 刪除失敗,雖然有著 K8s 面向終態(tài)的理念,組件會不斷重試,但終究也會存在臟數(shù)據(jù),如 pod 在 etcd 上刪除,但是節(jié)點上還殘留著臟數(shù)據(jù)。我們設計實現(xiàn)了一個巡檢系統(tǒng),通過查詢 apiserver 獲取調(diào)度到當前節(jié)點上的 pods,通過對比,找到節(jié)點上殘留的進程/容器/volumes 目錄/cgroup /網(wǎng)絡設備等,通過其他途徑嘗試釋放殘留資源。
接下來描述故障機的處理流程。
故障機判斷的數(shù)據(jù)來源有很多,主要有節(jié)點的監(jiān)控指標,比如:
某類 Volume 掛載失敗
NPD(Node Problem Detector),這是社區(qū)的一個框架
Trace 系統(tǒng),比如某個節(jié)點上 Pod 創(chuàng)建持續(xù)報鏡像下載失敗
SLO,比如單機上殘留大量 Pod
我們開發(fā)了多個 Controller 對這些某類故障進行巡檢,形成故障機列表。一個故障機可以有好幾項故障。對于故障機,會按照故障進行不同的操作。主要的操作有:打 Taint,防止 Pod 調(diào)度上去;降低 Node 的優(yōu)先級;直接自動處理進行恢復。對于一些特殊原因,比如磁盤滿,那就需要人工介入排查。
故障機系統(tǒng)每天都會產(chǎn)生一個日報,來表明故障機系統(tǒng)今天做了哪些事情。開發(fā)人員可以通過不斷地添加 Controller 和處理規(guī)則完善整個故障機處理系統(tǒng)。
接下來,我們來分享下達到高 SLO 的一些方法。
第一點,在提升成功率的進程中,我們面臨的最大問題就是鏡像下載的問題。要知道,Pod 必須在規(guī)定時間內(nèi)交付,而鏡像下載通常需要非常多的時間。為此,我們通過計算鏡像下載時間,還專門設置了一個 ImagePullCostTime 的錯誤,即鏡像下載時間太長,導致 Pod 無法按時交付。
還好,阿里鏡像分發(fā)平臺 Dragonfly 支持了 Image lazyload 技術(shù),也就是支持遠程鏡像,在 Kubelet 創(chuàng)建容器時,不用再下載鏡像。所以,這大大加速了 Pod 的交付速度。有關(guān) Image lazyload 技術(shù),大家可以看下阿里 Dragonfly 的分享。
第二點,對于提升單個 Pod 成功率,隨著成功率的提升,難度也越來越難??梢砸胍恍?workload 進行重試。在螞蟻,paas 平臺會不斷重試,直到 Pod 成功交付或者超時。當然,在重試時,之前的失敗的節(jié)點需要排除。
第三點,關(guān)鍵的 Daemonset 一定要進行檢查,如果關(guān)鍵 Daemonset 缺失,而把 Pod 調(diào)度上去,就非常容易出問題,從而影響創(chuàng)建/刪除鏈路。這需要接入故障機體系。
第四點,很多 Plugin,如 CSI Plugin,是需要向 Kubelet 注冊的。可能存在節(jié)點上一切正常,但向 Kubelet 注冊的時候失敗,這個節(jié)點同樣無法提供 Pod 交付的服務,需要接入故障機體系。
最后一點,由于集群中的用戶數(shù)量是非常多的,所以隔離非常重要。在權(quán)限隔離的基礎(chǔ)上,還需要做到 QPS 隔離,及容量的隔離,防止一個用戶的 Pod 把集群能力耗盡,從而保障其他用戶的利益。
關(guān)于在大規(guī)模 Kubernetes 集群上實現(xiàn)高 SLO 的方法是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。