本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

API 優先順序和公平性 Alpha

這篇部落格文章描述了“API 優先順序和公平性”,這是 Kubernetes 1.18 中的一個新 alpha 特性。API 優先順序和公平性允許叢集管理員將控制平面的併發性劃分為不同的加權優先順序級別。每個到達 kube-apiserver 的請求都將被歸類到其中一個優先順序級別,並獲得其在控制平面吞吐量中的公平份額。

這解決了什麼問題?

目前,apiserver 有一個簡單的機制來保護自身免受 CPU 和記憶體過載:對修改和只讀請求的最大併發限制。除了修改和只讀的區別之外,請求之間沒有其他區別;因此,可能會出現不良情況,即某些請求子集會擠佔其他請求。

簡而言之,Kubernetes 工作負載太容易意外地對 apiserver 進行拒絕服務攻擊 (DoS),導致其他重要流量(例如系統控制器或領導者選舉)間歇性失敗。在最糟糕的情況下,少數損壞的節點或控制器可能會使繁忙的叢集陷入崩潰邊緣,將區域性問題轉化為控制平面中斷。

我們如何解決這個問題?

新特性“API 優先順序和公平性”旨在概括每個 apiserver 中現有的最大併發請求處理程式,使行為更加智慧和可配置。總體方法如下:

  1. 每個請求都由一個 _Flow Schema_ 匹配。Flow Schema 說明了匹配請求的優先順序級別,併為這些請求分配一個“流識別符號”。流識別符號是系統判斷請求是否來自同一源的方式。
  2. 優先順序級別可以配置為以多種方式執行。每個優先順序級別都有自己的獨立併發池。優先順序級別還引入了排隊無法立即處理的請求的概念。
  3. 為了防止任何一個使用者或名稱空間壟斷一個優先順序級別,可以將其配置為擁有多個佇列。使用 “隨機分片 (Shuffle Sharding)” 來將每個請求流分配到佇列的子集。
  4. 最後,當有能力處理請求時,使用 “公平排隊 (Fair Queuing)” 演算法來選擇下一個請求。在每個優先順序級別內,佇列以相同的公平性競爭。

早期結果非常有前景!請檢視此 分析

我該如何試用這個功能?

為了試用此功能,您需要準備以下事項

  • 下載並安裝 v1.18.0 或更高版本的 kubectl
  • 在 kube-apiserver 上使用命令列標誌 --runtime-config="flowcontrol.apiserver.k8s.io/v1alpha1=true" 啟用新的 API 組
  • 在 kube-apiserver 上使用命令列標誌 --feature-gates=APIPriorityAndFairness=true 開啟特性門控

成功啟動 kube-apiservers 後,您將在叢集中看到一些預設的 FlowSchema 和 PriorityLevelConfiguration 資源。這些預設配置旨在為您的叢集提供通用的保護和流量管理。您可以使用常用工具(例如)檢查和自定義預設配置:

  • kubectl get flowschemas
  • kubectl get prioritylevelconfigurations

這個功能是如何在底層工作的?

請求到達處理程式後,會被精確地分配到一個優先順序級別以及該優先順序級別內的一個流。因此,理解 FlowSchema 和 PriorityLevelConfiguration 如何工作將有助於您管理透過 kube-apiservers 的請求流量。

  • FlowSchema:FlowSchema 將標識一個 PriorityLevelConfiguration 物件以及計算請求“流識別符號”的方式。目前我們支援根據請求的發起者身份、動詞和目標物件來匹配請求。身份可以根據:使用者名稱、使用者組名或 ServiceAccount 進行匹配。至於目標物件,我們可以透過 apiGroup、resource[/subresource] 和 namespace 進行匹配。

    • 流識別符號用於隨機分片,因此如果請求來自同一源,則請求具有相同的流識別符號很重要!我們喜歡考慮“大象”(傳送許多/大量請求)與“小鼠”(傳送少量/輕量請求)的場景:重要的是要確保大象的請求都獲得相同的流識別符號,否則它們在系統中看起來會像許多不同的小鼠!
    • 請參閱 此處 的 API 文件!
  • PriorityLevelConfiguration:定義一個優先順序級別。

    • 對於 apiserver 自身請求和任何可重入流量(例如,自身發出 API 請求的准入 webhook),優先順序級別可以標記為“exempt”(豁免),這意味著不進行任何型別的排隊或限制。這是為了防止優先順序反轉。
    • 每個非豁免優先順序級別都配置有一定數量的“併發份額”,並獲得一個獨立的併發池來使用。該優先順序級別的請求在該池未滿時在該池中執行,絕不在其他地方執行。每個 apiserver 都配置有總併發限制(視為修改和只讀請求的舊限制之和),然後根據優先順序級別的併發份額按比例分配給各個優先順序級別。
    • 一個非豁免的優先順序級別可以選擇用於隨機分片的佇列數量和“手牌大小 (hand size)”。隨機分片將流對映到佇列的方式優於一致性雜湊。給定的流可以訪問一小部分佇列,對於每個傳入請求,選擇最短的佇列。當一個優先順序級別有佇列時,它也會設定佇列長度的限制。還有一個限制是請求可以在其佇列中等待多長時間;這等於 apiserver 請求超時的一個固定比例。無法執行且無法(再)排隊的請求將被拒絕。
    • 或者,非豁免優先順序級別可以選擇立即拒絕,而不是在佇列中等待。
    • 請參閱此功能的 API 文件

還缺少什麼?什麼時候會有 Beta 版本?

我們已經在根據 alpha 版本規劃一些增強功能,隨著使用者向社群傳送反饋,還會增加更多。以下是其中的一些列表:

  • WATCH 和 EXEC 請求的流量管理
  • 調整和改進 FlowSchema/PriorityLevelConfiguration 的預設集
  • 增強此功能的可觀察性
  • 在此處加入討論

可能會根據 LIST 請求的結果大小估計值,區別對待它們。

我該如何參與?

一如既往!在 Slack 上聯絡我們 #sig-api-machinery,或透過 郵件列表。我們有許多令人興奮的功能需要構建,可以使用各種幫助。

非常感謝為該功能做出貢獻的開發者:Aaron Prindle, Daniel Smith, Jonathan Tomer, Mike Spreitzer, Min Kim, Bruce Ma, Yu Liao, Mengyi Zhou!