天天看點

在大規模 Kubernetes 叢集上實作高 SLO 的方法

随着 Kubernetes 叢集規模和複雜性的增加,叢集越來越難以保證高效率、低延遲的傳遞 pod。本文将分享螞蟻金服在設計 SLO 架構和實作高 SLO 的方法和經驗。

在大規模 Kubernetes 叢集上實作高 SLO 的方法
作者 | 螞蟻金服技術專家 姚菁華;螞蟻金服進階開發工程師 範康

導讀:随着 Kubernetes 叢集規模和複雜性的增加,叢集越來越難以保證高效率、低延遲的傳遞 pod。本文将分享螞蟻金服在設計 SLO 架構和實作高 SLO 的方法和經驗。

Why SLO?

在大規模 Kubernetes 叢集上實作高 SLO 的方法

Gartner 對 SLO 的定義:在 SLA 架構下,SLO 是系統必須要達到的目标;需要盡可能地保障調用方的成功。有些人可能會對 SLI/SLO/SLA 有困惑,可以先來看下三者的關系:

  • SLI 定義一個名額,來描述一個服務有多好算達到好的标準。比如 Pod 在 1min 内傳遞。我們通常從遲延、可用性、吞吐率及成功率這些角度來制定 SLI。
  • SLO 定義了一個小目标,來衡量一個 SLI 名額在一段時間内達到好的标準的比例。比如說,99% 的 Pod 在 1min 内傳遞。當一項服務公布了其 SLO 的以後,使用者方就會對該服務的品質有了期望。
  • **SLA **是 SLO 衍生出來的協定,常用于 SLO 定義的目标比例沒有完成時,服務方要賠多少錢。通常來說,SLA 的協定會具體白紙黑字形成有法律效率的合同,常用于服務供應商和外部客戶之間(例如阿裡雲和阿裡雲的使用者)。一般來說對于内部服務之間的 SLO 被打破,通常不會是經濟上的賠償,可能更多的是職責上的認定。

是以,我們在系統内部更多關注的是 SLO。

What we concern about Larger K8s Cluster?

在大規模 Kubernetes 叢集上實作高 SLO 的方法

随着生産環境不斷發展、K8s 叢集越來越複雜、叢集規模不斷增大。如何保障大規模環境 K8s 叢集的可用性?是擺在衆多廠家面前的一個難題。對于 K8s 叢集,我們通常關心以下幾個問題:

  • 第一個問題就是叢集是否健康,所有元件是否正常工作,叢集中 Pod 建立的失敗數量有多少,這是一個整體名額的問題。
  • 第二個問題就是叢集中發生了什麼,叢集中是否有異常發生了,使用者在叢集中做了些什麼事情,這是一個追蹤能力的問題。
  • 第三個問題就是有了異常後,是哪個元件出了問題導緻成功率降低,這是一個原因定位的問題。

那麼,我們該如何解決上面的問題呢?

  • 首先,我們要定義一套 SLO,來描述叢集的可用性。
  • 接着,我們必須有能力對叢集中 Pod 的生命周期進行追蹤;對于失敗的 Pod,還需要分析出失敗原因,以快速定位異常元件。
  • 最後,我們要通過優化手段,消除叢集的異常。

SLls on Large K8s Cluster

我們先來看下叢集的一些名額。

在大規模 Kubernetes 叢集上實作高 SLO 的方法
  • 第一項名額:叢集健康度。目前有 Healthy/Warning/Fatal 三個值來描述,Warning 和 Fatal 對應着告警體系,比如 P2 告警發生,那叢集就是 Warning;如果 P0 告警發生,那叢集就是 Fatal,必須進行處理。
  • 第二項名額:成功率。這裡的成功率是指 Pod 的建立成功率。Pod 成功率是一個非常重要的名額,螞蟻一周 Pod 建立量是百萬級的,成功率的波動會造成大量 Pod 的失敗;而且 Pod 成功率的下跌,是叢集異常的最直覺反應。
  • 第三項名額:殘留 Terminating Pod 的數量。為什麼不用删除成功率呢?因為在百萬級别的時候,即使 Pod 删除成功率達到 99.9%,那麼 Terminating Pod 的數量也是千級别的。殘留如此多的 Pod,會占着應用的容量,在生産環境中是不可接受的。
  • 第四項名額:服務線上率。服務線上率是通過探針來衡量的,探針失敗,意味着叢集不可用。服務線上率是會對 Master 元件來設計的。
  • 最後一項名額:故障機數量,這是一個節點次元的名額。故障機通常是指那些無法正确傳遞 Pod 的實體機,可能是磁盤滿了,可能是 load 太高了。叢集故障機并須做到“快速發現,快速隔離,及時修複”,畢竟故障機會對叢集容量造成影響。

The success standard and reason classification

有了叢集的名額後,我們需要把這些名額進行細化,定義出成功的标準。

在大規模 Kubernetes 叢集上實作高 SLO 的方法

先來看 Pod 建立成功率名額。我們把 Pod 分為了普通 Pod 和 Job 類 Pob。普通 Pod 的 RestartPolicy 為 Always,Job 類 Pod 的 RestartPlicy 為 Never 或 OnFailure。兩者都設定有傳遞時間,比如必須在 1 分鐘以内完成傳遞。普通 Pod 的傳遞标準是 1min 内 Pod 已經 Ready;Job 類 Pod 的傳遞标準是 1min 内 Pod 的狀态已達 Running、Succeeded 或 Failed。當然建立的時間需要把 PostStartHook 執行時間排除。

對于 Pod 的删除,成功的标準為:在規定時間内,Pod 從 ETCD 内删除。當然,删除的時間需要把 PreStopHookPeriod 時間排除。

對于故障機,要盡快的發現并進行隔離和降級。比如實體機磁盤隻讀,那必須在 1min 内完成對該 Pod 打 taint。至于故障機的恢複時間,需要按不同的故障原因,制定不同的恢複時間。比如系統故障需要重要安裝系統,那恢複時間就會長些。

有了這些标準後,我們也對 Pod 失敗的原因進行了整理,有些失敗原因是系統引起的,是我們需要關心的;有些失敗原因是使用者引發的,是我們不需要關心的。

比如 RuntimeError,就是一個系統錯誤,底層 Runtime 有問題了;ImagePullFailed,Kubelet 下載下傳鏡像失敗,由于螞蟻有 Webhook 對鏡像準入做了校驗,所有鏡像下載下傳失敗一般都是系統原因造成的。

對于使用者原因,在系統側無法解決,我們隻把這些失敗原因以接口查詢的方式提供給使用者,讓使用者自己解決。比如 ContainerCrashLoopBackOff,通常是由使用者容器退出引起的。

The infrastructure

在大規模 Kubernetes 叢集上實作高 SLO 的方法

圍繞 SLO 目标,我們建構了一整套體系,一方面用于向終端使用者、運維人員展示目前叢集各項名額狀;另一方面,各個元件互相協作,通過分析目前叢集狀态,得到影響 SLO 的各項因素,為提升叢集 pod 傳遞成功率提供資料支援。

自頂向下而看,頂層元件主要面向各種名額資料, 如叢集健康狀态、pod 建立、删除、更新成功率,殘留 pods 數量、不健康節點數量等名額。其中 Display Board 就是我們常說的監控大盤。

我們同樣建構了 Alert 告警子系統,支援靈活的配置方式,可以為不同的名額,根據名額的下跌百分比,名額下跌絕對值等配置多種告警方式,如電話,短信,郵件等。

Analysis System 通過分析名額曆史資料,以及采集到的節點 metrics 和 master 元件名額,給出更詳細的叢集營運報告。其中:

  • Weekly Report 子系統給出目前叢集本周 pod 建立/删除/更新的資料統計,以及失敗案例原因彙總。
  • Terminating Pods Number 給出一段時間内叢集内新增的無法通過 K8s 機制删除的 pods 清單和 pods 殘留原因。
  • Unhealthy Nodes 則給出一個周期内叢集所有節點的總可用時間占比,每個節點的可用時間,運維記錄,以及不能自動恢複,需要人工介入恢複的節點清單。

為了支撐上述這些功能,我們開發了 Trace System,用來分析展示單個 pod 建立/删除/更新失敗的具體原因。其中包含日志和事件采集、資料分析和 pod 生命周期展示三個子產品:

  • 日志和事件采集子產品采集各 master 元件以及節點元件的運作日志和 pod/node 事件,分别以 pod/node 為索引存儲日志和事件。
  • 資料分析子產品分析還原出 pod 生命周期中各階段用時,以及判斷 pod 失敗原因及節點不可用原因。
  • 最後,由 Report 子產品向終端使用者暴露接口和 UI,向終端使用者展示 pod 生命周期以及出錯原因。

The trace system

接下來,以一個 pod 建立失敗案例為例,向大家展示下 tracing 系統的工作流程。

在大規模 Kubernetes 叢集上實作高 SLO 的方法

使用者輸入 pod uid 之後,tracing system 通過 pod 索引,查找到 pod 對應生命周期分析記錄、傳遞成功與否判定結果。當然,storage 存儲的資料不僅為終端使用者提供基礎資料,更重要的是通過對叢集内 pods 生命周期,分析出周期内叢集的營運狀況及每個節點的營運狀況。比如說叢集内太多 pods 排程到熱點節點,不同 pods 的傳遞引起節點上資源競争,導緻節點負載太高,而傳遞能力卻在下降,最終表現為節點上 pods 傳遞逾時。

再舉個例子,通過曆史統計資料,分析出 pods 生命周期中各階段的執行時間基線,以基線為評估标準,比較元件不同版本的平均用時、用時分布,給出元件改進建議。另外,通過整體的 pods 生命周期中各元件負責的步驟時間占比,找出占比較多的步驟,為後續優化 pod 傳遞時間提供資料支援。

Node Metrics

在大規模 Kubernetes 叢集上實作高 SLO 的方法

一個運作狀況良好的叢集,不僅需要 master 元件保持高可用,節點穩定性也不容忽視。

如果把 pod 建立比作是 rpc 調用,則每個節點就是一個 rpc 服務提供者,叢集的總容量等于每個節點能處理的 pod 建立請求的總和。每多一個不可用的節點,都代表着叢集傳遞能力的下降,也代表着叢集可用資源的下降,這就要求盡量保證叢集内節點高可用;每一次 pod 傳遞/删除/更新失敗,也意味着使用者使用成本上升,體驗下降,這就要求叢集節點隻有保證良好的健康度,排程到節點上的 pods 才能成功傳遞。

換句話說,不僅要盡早發現節點異常,也要盡快修複節點。通過分析各元件在 pod 傳遞鍊路上的功能,我們補充了各種不同類型的元件的 metrics,以及将 host 運作狀态轉換為 metrics,一并采集到資料庫之後,結合每個節點上 pod 傳遞結果,可以構模組化型預測節點可用性,分析節點是否存在不可恢複異常,适當調整節點在排程器中比重,進而提升 pod 傳遞成功率。

Pod 建立/更新失敗,使用者可以通過重試來解決,但 pod 删除失敗,雖然有着 K8s 面向終态的理念,元件會不斷重試,但終究也會存在髒資料,如 pod 在 etcd 上删除,但是節點上還殘留着髒資料。我們設計實作了一個巡檢系統,通過查詢 apiserver 擷取排程到目前節點上的 pods,通過對比,找到節點上殘留的程序/容器/volumes 目錄/cgroup /網絡裝置等,通過其他途徑嘗試釋放殘留資源。

Unhealthy node

接下來描述故障機的處理流程。

在大規模 Kubernetes 叢集上實作高 SLO 的方法

故障機判斷的資料來源有很多,主要有節點的監控名額,比如:

  • 某類 Volume 挂載失敗
  • NPD(Node Problem Detector),這是社群的一個架構
  • Trace 系統,比如某個節點上 Pod 建立持續報鏡像下載下傳失敗
  • SLO,比如單機上殘留大量 Pod

我們開發了多個 Controller 對這些某類故障進行巡檢,形成故障機清單。一個故障機可以有好幾項故障。對于故障機,會按照故障進行不同的操作。主要的操作有:打 Taint,防止 Pod 排程上去;降低 Node 的優先級;直接自動處理進行恢複。對于一些特殊原因,比如磁盤滿,那就需要人工介入排查。

故障機系統每天都會産生一個日報,來表明故障機系統今天做了哪些事情。開發人員可以通過不斷地添加 Controller 和處理規則完善整個故障機處理系統。

Tips on increasing SLO

接下來,我們來分享下達到高 SLO 的一些方法。

在大規模 Kubernetes 叢集上實作高 SLO 的方法
  • 第一點,在提升成功率的程序中,我們面臨的最大問題就是鏡像下載下傳的問題。要知道,Pod 必須在規定時間内傳遞,而鏡像下載下傳通常需要非常多的時間。為此,我們通過計算鏡像下載下傳時間,還專門設定了一個 ImagePullCostTime 的錯誤,即鏡像下載下傳時間太長,導緻 Pod 無法按時傳遞。

還好,阿裡鏡像分發平台 Dragonfly 支援了 Image lazyload 技術,也就是支援遠端鏡像,在 Kubelet 建立容器時,不用再下載下傳鏡像。是以,這大大加速了 Pod 的傳遞速度。有關 Image lazyload 技術,大家可以看下阿裡 Dragonfly 的分享。

  • 第二點,對于提升單個 Pod 成功率,随着成功率的提升,難度也越來越難。可以引入一些 workload 進行重試。在螞蟻,paas 平台會不斷重試,直到 Pod 成功傳遞或者逾時。當然,在重試時,之前的失敗的節點需要排除。
  • 第三點,關鍵的 Daemonset 一定要進行檢查,如果關鍵 Daemonset 缺失,而把 Pod 排程上去,就非常容易出問題,進而影響建立/删除鍊路。這需要接入故障機體系。
  • 第四點,很多 Plugin,如 CSI Plugin,是需要向 Kubelet 注冊的。可能存在節點上一切正常,但向 Kubelet 注冊的時候失敗,這個節點同樣無法提供 Pod 傳遞的服務,需要接入故障機體系。
  • 最後一點,由于叢集中的使用者數量是非常多的,是以隔離非常重要。在權限隔離的基礎上,還需要做到 QPS 隔離,及容量的隔離,防止一個使用者的 Pod 把叢集能力耗盡,進而保障其他使用者的利益。

阿裡雲首場 Serverless 開發者線下沙龍亮相北京

本次線下活動将邀請來自阿裡雲、淘寶、閑魚、百富旅行等國内一線 Serverless 技術專家,為開發者帶來:

  • 淘寶/天貓應對 雙11 流量洪峰如何規模化實踐 Serverless。
  • 切中開發者痛點,講述閑魚、百富旅行等中國企業的 Serverless 落地及“踩坑”經驗。
  • 首次披露阿裡雲最新開源工具鍊 Serverless Devs 設計詳情及未來走向。

點選連結立即報名:https://www.huodongxing.com/event/9570184556300

“阿裡巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公衆号。”