API 優先順序和公平性

特性狀態: Kubernetes v1.29 [stable]

在過載情況下控制 Kubernetes API 伺服器的行為是叢集管理員的一項關鍵任務。kube-apiserver 具有一些可用控制元件(即 `—max-requests-inflight` 和 `—max-mutating-requests-inflight` 命令列引數)來限制將接受的未完成工作的數量,防止入站請求的洪水使 API 伺服器過載並可能導致其崩潰,但這些標誌不足以確保在流量高峰期最重要的請求能夠透過。

API 優先順序和公平性功能 (APF) 是一種替代方案,它改進了上述最大進行中請求的限制。APF 以更細粒度的方式對請求進行分類和隔離。它還引入了有限的佇列,因此在非常短暫的突發情況下不會拒絕任何請求。請求使用公平排隊技術從佇列中分派,這樣,例如,行為不當的控制器就不會餓死其他控制器(即使在同一優先順序級別)。

此功能旨在與標準控制器配合良好,標準控制器使用 Informer 並透過指數退避來響應 API 請求失敗,以及其他以這種方式工作的客戶端。

啟用/停用 API 優先順序和公平性

API 優先順序和公平性功能由命令列引數控制,並且預設啟用。有關可用 kube-apiserver 命令列選項及其啟用和停用方式的通用說明,請參閱選項。APF 的命令列選項名稱是“—enable-priority-and-fairness”。此功能還涉及一個API 組,其中包含:(a) 穩定的 `v1` 版本,在 1.29 中引入,預設啟用;(b) `v1beta3` 版本,預設啟用,並在 v1.29 中棄用。您可以透過向 `kube-apiserver` 呼叫新增以下命令列引數來停用 API 組 Beta 版本 `v1beta3`

kube-apiserver \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta3=false \
 # …and other flags as usual

命令列引數 `—enable-priority-and-fairness=false` 將停用 API 優先順序和公平性功能。

遞迴伺服器場景

在遞迴伺服器場景中必須謹慎使用 API 優先順序和公平性。這些場景是指伺服器 A 在處理請求時,向伺服器 B 發出輔助請求。伺服器 B 甚至可能進一步向伺服器 A 發出輔助呼叫。在優先順序和公平性控制應用於原始請求和某些輔助請求(無論遞迴深度如何)的情況下,存在優先順序倒置和/或死鎖的危險。

遞迴的一個例子是 `kube-apiserver` 向伺服器 B 發出准入 Webhook 呼叫,在處理該呼叫時,伺服器 B 進一步向 `kube-apiserver` 發出輔助請求。遞迴的另一個例子是 `APIService` 物件指示 `kube-apiserver` 將有關某個 API 組的請求委託給自定義外部伺服器 B(這是“聚合”之一)。

當已知原始請求屬於某個優先順序級別,並且輔助受控請求被分類到更高的優先順序級別時,這是一種可能的解決方案。當原始請求可以屬於任何優先順序級別時,輔助受控請求必須免受優先順序和公平性限制。一種方法是使用下面討論的配置分類和處理的物件。另一種方法是完全停用伺服器 B 上的優先順序和公平性,使用上面討論的技術。第三種方法是當伺服器 B 不是 `kube-apisever` 時最簡單的使用方法,即在程式碼中停用伺服器 B 的優先順序和公平性。

概念

API 優先順序和公平性功能涉及幾個不同的特性。傳入請求透過FlowSchema根據請求屬性進行分類,並分配給優先順序級別。優先順序級別透過維護獨立的併發限制來增加一定程度的隔離,從而使分配給不同優先順序級別的請求不會相互餓死。在一個優先順序級別內,公平排隊演算法防止不同的請求相互餓死,並允許請求排隊以防止突發流量在平均負載可接受的低時導致請求失敗。

優先順序級別

未啟用 APF 時,API 伺服器中的總體併發由 `kube-apiserver` 標誌 `--max-requests-inflight` 和 `--max-mutating-requests-inflight` 限制。啟用 APF 後,這些標誌定義的併發限制會求和,然後將總和分配給一組可配置的優先順序級別。每個傳入請求都被分配到一個優先順序級別,每個優先順序級別只分派其特定限制允許的併發請求數量。

例如,預設配置包括用於領導選舉請求、來自內建控制器的請求以及來自 Pods 的請求的單獨優先順序級別。這意味著行為不當的 Pod 用請求淹沒 API 伺服器時,不會阻止領導選舉或內建控制器的操作成功。

優先順序級別的併發限制會定期調整,允許未充分利用的優先順序級別暫時將併發借給充分利用的級別。這些限制基於名義限制以及優先順序級別可以借出和借入多少併發的上限,所有這些都來自下面提到的配置物件。

請求佔用的座位

上面關於併發管理的描述是基線故事。請求具有不同的持續時間,但在任何給定時刻與優先順序級別的併發限制進行比較時,它們的計數是相等的。在基線故事中,每個請求佔用一個併發單元。“座位”這個詞用於表示一個併發單元,靈感來自於火車或飛機上的每位乘客佔用一個固定供應的座位的方式。

但是有些請求佔用不止一個座位。其中一些是伺服器估計會返回大量物件的**列表**請求。已發現這些請求給伺服器帶來了異常沉重的負擔。因此,伺服器會估計將返回的物件數量,並認為請求佔用的座位數量與該估計數量成比例。

watch 請求的執行時間調整

API 優先順序和公平性管理 **watch** 請求,但這涉及到一些偏離基線行為的額外情況。首先是 **watch** 請求佔用其座位的時間。根據請求引數,對 **watch** 請求的響應可能以或不以所有相關預先存在物件的 **create** 通知開始。API 優先順序和公平性認為 **watch** 請求在其初始突發通知(如果有)結束後就完成了其座位佔用。

每當伺服器收到物件建立/更新/刪除通知時,正常通知就會併發地傳送到所有相關的 **watch** 響應流。為了考慮這項工作,API 優先順序和公平性認為每個寫入請求在實際寫入完成後會額外佔用一些時間。伺服器估計將傳送的通知數量,並調整寫入請求的座位數量和座位佔用時間以包括這項額外工作。

排隊

即使在同一優先順序級別內,也可能存在大量不同的流量來源。在過載情況下,防止一個請求流餓死其他請求(特別是,在單個有缺陷的客戶端用請求淹沒 kube-apiserver 的相對常見情況下,理想情況下,該有缺陷的客戶端對其他客戶端幾乎沒有可衡量的影響)是很有價值的。這透過使用公平排隊演算法來處理分配給同一優先順序級別的請求來解決。每個請求都被分配到一個,該流由匹配的 FlowSchema 的名稱加上一個流區分符(即請求使用者、目標資源的名稱空間或無)標識,並且系統嘗試對同一優先順序級別中不同流的請求給予大致相等的權重。為了實現不同例項的獨立處理,具有多個例項的控制器應該使用不同的使用者名稱進行認證。

將請求分類到流後,API 優先順序和公平性功能可能會將請求分配到佇列。這種分配使用一種稱為隨機分片的技術,該技術能相對高效地利用佇列來隔離低強度流與高強度流。

排隊演算法的細節可以針對每個優先順序級別進行調整,允許管理員權衡記憶體使用、公平性(當總流量超過容量時,獨立流都將取得進展的特性)、對突發流量的容忍度以及排隊引起的額外延遲。

豁免請求

有些請求被認為是足夠重要的,因此它們不受此功能施加的任何限制。這些豁免可以防止配置不當的流控制配置完全停用 API 伺服器。

資源

流控制 API 涉及兩種資源。PriorityLevelConfiguration 定義了可用的優先順序級別、每個級別可以處理的可用併發預算份額,並允許微調排隊行為。FlowSchema 用於分類單個入站請求,將每個請求匹配到單個 PriorityLevelConfiguration。

PriorityLevelConfiguration

PriorityLevelConfiguration 表示單個優先順序級別。每個 PriorityLevelConfiguration 對未完成請求的數量和排隊請求的數量都有獨立的限制。

PriorityLevelConfiguration 的名義併發限制不是以絕對的座位數指定,而是以“名義併發份額”指定。API 伺服器的總併發限制按照這些份額的比例分配給現有的 PriorityLevelConfiguration,以便為每個級別提供其名義座位限制。這允許叢集管理員透過重新啟動 `kube-apiserver` 併為 `--max-requests-inflight`(或 `--max-mutating-requests-inflight`)設定不同的值來增加或減少伺服器的總流量,並且所有 PriorityLevelConfiguration 都將看到其最大允許併發以相同的比例增加(或減少)。

優先順序級別可以借出和借入多少併發的上限在 PriorityLevelConfiguration 中表示為該級別名義限制的百分比。透過將名義限制/100.0 相乘並四捨五入,將其解析為絕對的座位數。優先順序級別的動態調整併發限制被限制在(a)其名義限制減去其可借出座位數的下限和(b)其名義限制加上其可借入座位數的上限之間。每次調整時,動態限制由每個優先順序級別回收最近出現需求的所有已借出座位,然後在上述限制內共同公平地響應優先順序級別的最近座位需求。

當分配給單個 PriorityLevelConfiguration 的入站請求量超過其允許的併發級別時,其規範的 `type` 欄位決定了額外請求的處理方式。型別為 `Reject` 意味著超出流量將立即被拒絕,並返回 HTTP 429(請求過多)錯誤。型別為 `Queue` 意味著超過閾值的請求將被排隊,並使用隨機分片和公平排隊技術來平衡請求流之間的進度。

排隊配置允許對優先順序級別的公平排隊演算法進行微調。該演算法的詳細資訊可以在增強提案中閱讀,簡而言之,就是:

  • 增加 `queues` 會降低不同流之間的衝突率,但會增加記憶體使用量。此處的值為 1 實際上會停用公平排隊邏輯,但仍允許請求排隊。

  • 增加 `queueLengthLimit` 允許在不丟棄任何請求的情況下維持更大的突發流量,但會增加延遲和記憶體使用量。

  • 更改 `handSize` 允許您調整不同流之間發生衝突的機率以及在過載情況下單個流可用的總體併發性。

下表顯示了一個有趣的洗牌分片配置集合,顯示了對於每個配置,在說明性的大象(高強度流)數量下,給定老鼠(低強度流)被大象壓扁的機率。請參閱 https://play.golang.org/p/Gi0PLgVHiUg,它計算了此表。

示例洗牌分片配置
HandSize佇列1 只大象4 只大象16 只大象
12324.428838398950118e-090.114313488300991440.9935089607656024
10321.550093439632541e-080.06264798402235450.9753101519027554
10646.601827268370426e-120.000455713209903707760.49999929150089345
9643.6310049976037345e-110.000455012123041122730.4282314876454858
8642.25929199850899e-100.00048866970530404460.35935114681123076
81286.994461389026097e-133.4055790161620863e-060.02746173137155063
71281.0579122850901972e-116.960839379258192e-060.02406157386340147
72567.597695465552631e-146.728547142019406e-080.0006709661542533682
62562.7134626662687968e-122.9516464018476436e-070.0008895654642000348
65124.116062922897309e-144.982983350480894e-092.26025764343413e-05
610246.337324016514285e-168.09060164312957e-114.517408062903668e-07

FlowSchema

FlowSchema 匹配一些入站請求並將它們分配給一個優先順序級別。每個入站請求都會針對 FlowSchema 進行測試,從數字上最低的 `matchingPrecedence` 開始,然後向上進行。第一個匹配的 FlowSchema 獲勝。

如果 FlowSchema 的至少一個 `rules` 匹配,則該 FlowSchema 匹配給定的請求。如果其至少一個 `subjects` **以及**至少一個 `resourceRules` 或 `nonResourceRules`(取決於傳入請求是針對資源還是非資源 URL)匹配請求,則該規則匹配。

對於 subject 中的 `name` 欄位,以及資源和非資源規則的 `verbs`、`apiGroups`、`resources`、`namespaces` 和 `nonResourceURLs` 欄位,可以指定萬用字元 `*` 來匹配給定欄位的所有值,從而有效地將其從考慮中移除。

FlowSchema 的 `distinguisherMethod.type` 決定了匹配該 schema 的請求如何分離到流中。它可以是 `ByUser`,在這種情況下,一個請求使用者將無法餓死其他使用者的容量;`ByNamespace`,在這種情況下,一個名稱空間中資源的請求將無法餓死其他名稱空間中資源的容量;或者為空(或 `distinguisherMethod` 可以完全省略),在這種情況下,所有由該 FlowSchema 匹配的請求都將被視為單個流的一部分。給定 FlowSchema 的正確選擇取決於資源和您的特定環境。

預設值

每個 kube-apiserver 都維護兩種 APF 配置物件:強制性配置物件和建議性配置物件。

強制性配置物件

這四個強制配置物件反映了固定的內建防護行為。在這些物件存在之前,伺服器就具有這種行為,當這些物件存在時,它們的規範反映了這種行為。這四個強制物件如下。

  • 強制性的 `exempt` 優先順序級別用於完全不受流控制的請求:它們將始終立即分派。強制性的 `exempt` FlowSchema 將來自 `system:masters` 組的所有請求分類到此優先順序級別。如果適用,您可以定義其他 FlowSchema,將其他請求定向到此優先順序級別。

  • 強制性的 `catch-all` 優先順序級別與強制性的 `catch-all` FlowSchema 結合使用,以確保每個請求都能得到某種分類。通常,您不應依賴此全捕獲配置,而應建立自己的全捕獲 FlowSchema 和 PriorityLevelConfiguration(或使用預設安裝的建議的 `global-default` 優先順序級別)。由於不期望正常使用,強制性的 `catch-all` 優先順序級別具有非常小的併發份額,並且不排隊請求。

建議的配置物件

建議的 FlowSchema 和 PriorityLevelConfiguration 構成了合理的預設配置。如果您願意,可以修改這些或建立額外的配置物件。如果您的叢集可能會遇到高負載,您應該考慮哪種配置效果最好。

建議配置將請求分組為六個優先順序級別

  • `node-high` 優先順序級別用於節點的健康更新。

  • `system` 優先順序級別用於來自 `system:nodes` 組(即 Kubelets)的非健康請求,它們必須能夠聯絡 API 伺服器才能在其上排程工作負載。

  • `leader-election` 優先順序級別用於內建控制器(特別是來自 `system:kube-controller-manager` 或 `system:kube-scheduler` 使用者以及 `kube-system` 名稱空間中的服務賬號的 `endpoints`、`configmaps` 或 `leases` 請求)的領導選舉請求。將這些請求與其他流量隔離非常重要,因為領導選舉失敗會導致其控制器失敗並重新啟動,這反過來又會隨著新控制器同步其 informer 而導致更昂貴的流量。

  • `workload-high` 優先順序級別用於來自內建控制器的其他請求。

  • `workload-low` 優先順序級別用於來自任何其他服務帳戶的請求,通常包括來自 Pod 中執行的所有控制器的請求。

  • `global-default` 優先順序級別處理所有其他流量,例如非特權使用者執行的互動式 `kubectl` 命令。

建議的 FlowSchema 用於將請求導向上述優先順序級別,此處不再贅述。

強制性配置物件和建議性配置物件的維護

每個 `kube-apiserver` 使用初始和週期性行為獨立維護強制性和建議性配置物件。因此,在不同版本伺服器混合的情況下,只要不同伺服器對這些物件的正確內容有不同意見,就可能會出現抖動。

每個 `kube-apiserver` 對強制性和建議性配置物件進行初始維護,之後對這些物件進行定期維護(每分鐘一次)。

對於強制配置物件,維護包括確保物件存在,並且如果存在,則具有正確的規範。伺服器拒絕允許建立或更新與伺服器防護行為不一致的規範。

建議配置物件的維護旨在允許覆蓋其規範。另一方面,刪除不被尊重:維護將恢復該物件。如果您不想要建議的配置物件,則需要保留它但將其規範設定為具有最小影響。建議物件的維護還旨在支援在推出新版本 `kube-apiserver` 時自動遷移,儘管在伺服器混合存在時可能會出現抖動。

建議配置物件的維護包括:如果物件不存在,則使用伺服器建議的規範建立它。另一方面,如果物件已經存在,則維護行為取決於 `kube-apiservers` 或使用者是否控制該物件。在前一種情況下,伺服器確保物件的規範是伺服器建議的;在後一種情況下,規範保持不變。

誰控制物件的答案首先透過查詢鍵為 `apf.kubernetes.io/autoupdate-spec` 的註解來回答。如果存在這樣的註解且其值為 `true`,則 kube-apiservers 控制該物件。如果存在這樣的註解且其值為 `false`,則使用者控制該物件。如果以上兩種情況都不成立,則會檢視物件的 `metadata.generation`。如果其值為 1,則 kube-apiservers 控制該物件。否則,使用者控制該物件。這些規則是在 1.22 版本中引入的,其對 `metadata.generation` 的考慮是為了從更簡單的早期行為進行遷移。希望控制建議配置物件的使用者應將其 `apf.kubernetes.io/autoupdate-spec` 註解設定為 `false`。

強制或建議配置物件的維護還包括確保其具有 `apf.kubernetes.io/autoupdate-spec` 註解,該註解準確反映 kube-apiservers 是否控制該物件。

維護還包括刪除既不是強制也不是建議但被註解為 `apf.kubernetes.io/autoupdate-spec=true` 的物件。

健康檢查併發豁免

建議配置並未對 kube-apiserver 上來自其本地 kubelet 的健康檢查請求提供特殊處理——這些請求傾向於使用安全埠但未提供憑據。在建議配置下,這些請求被分配給 `global-default` FlowSchema 和相應的 `global-default` 優先順序級別,在那裡其他流量可能會將其擠出。

如果您新增以下額外的 FlowSchema,這將使這些請求免受速率限制。

apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
  name: health-for-strangers
spec:
  matchingPrecedence: 1000
  priorityLevelConfiguration:
    name: exempt
  rules:
    - nonResourceRules:
      - nonResourceURLs:
          - "/healthz"
          - "/livez"
          - "/readyz"
        verbs:
          - "*"
      subjects:
        - kind: Group
          group:
            name: "system:unauthenticated"

可觀測性

指標

啟用 API 優先順序和公平性功能後,kube-apiserver 會匯出額外的指標。監控這些指標可以幫助您確定您的配置是否不適當地限制了重要流量,或者發現可能損害系統健康的、行為不當的工作負載。

成熟度級別 BETA

  • `apiserver_flowcontrol_rejected_requests_total` 是一個計數器向量(自伺服器啟動以來的累計值),表示被拒絕的請求,按 `flow_schema`(指示匹配請求的 FlowSchema)、`priority_level`(指示分配給請求的優先順序級別)和 `reason` 標籤細分。`reason` 標籤將是以下值之一:

    • `queue-full`,表示排隊請求過多。
    • `concurrency-limit`,表示 PriorityLevelConfiguration 配置為拒絕而不是排隊額外請求。
    • `time-out`,表示請求在佇列中時其排隊時間限制已到期。
    • `cancelled`,表示請求未被清除鎖定並已從佇列中彈出。
  • `apiserver_flowcontrol_dispatched_requests_total` 是一個計數器向量(自伺服器啟動以來的累積值),表示已開始執行的請求,按 `flow_schema` 和 `priority_level` 細分。

  • `apiserver_flowcontrol_current_inqueue_requests` 是一個計量向量,儲存了瞬時排隊(未執行)請求的數量,按 `priority_level` 和 `flow_schema` 細分。

  • `apiserver_flowcontrol_current_executing_requests` 是一個計量向量,儲存了瞬時執行中(未在佇列中等待)請求的數量,按 `priority_level` 和 `flow_schema` 細分。

  • `apiserver_flowcontrol_current_executing_seats` 是一個計量向量,儲存了瞬時佔用的席位數量,按 `priority_level` 和 `flow_schema` 細分。

  • `apiserver_flowcontrol_request_wait_duration_seconds` 是一個直方圖向量,表示請求在佇列中等待的時間,按 `flow_schema`、`priority_level` 和 `execute` 標籤細分。`execute` 標籤指示請求是否已開始執行。

  • `apiserver_flowcontrol_nominal_limit_seats` 是一個計量向量,儲存每個優先順序級別的名義併發限制,該限制由 API 伺服器的總併發限制和優先順序級別配置的名義併發份額計算得出。

成熟度級別 ALPHA

  • `apiserver_current_inqueue_requests` 是一個計量向量,表示最近佇列請求數的最高水位線,按名為 `request_kind` 的標籤分組,其值為 `mutating` 或 `readOnly`。這些最高水位線描述了最近完成的一秒視窗中觀察到的最大數量。它們補充了舊的 `apiserver_current_inflight_requests` 計量向量,後者儲存了上一個視窗中正在主動服務的請求數的最高水位線。

  • `apiserver_current_inqueue_seats` 是一個計量向量,表示排隊請求中每個請求將佔用的最大座位數的總和,按標籤 `flow_schema` 和 `priority_level` 分組。

  • `apiserver_flowcontrol_read_vs_write_current_requests` 是一個直方圖向量,每納秒末對請求數量進行觀測,按 `phase` 標籤(取值 `waiting` 和 `executing`)和 `request_kind` 標籤(取值 `mutating` 和 `readOnly`)細分。每個觀測值都是一個比率,介於 0 到 1 之間,表示請求數量除以相應的請求限制(等待的佇列容量限制和執行的併發限制)。

  • `apiserver_flowcontrol_request_concurrency_in_use` 是一個計量向量,儲存瞬時佔用的座位數,按 `priority_level` 和 `flow_schema` 細分。

  • `apiserver_flowcontrol_priority_level_request_utilization` 是一個直方圖向量,每納秒末對請求數量進行觀測,按 `phase` 標籤(取值 `waiting` 和 `executing`)和 `priority_level` 細分。每個觀測值都是一個比率,介於 0 到 1 之間,表示請求數量除以相應的請求限制(等待的佇列容量限制和執行的併發限制)。

  • `apiserver_flowcontrol_priority_level_seat_utilization` 是一個直方圖向量,每納秒末對優先順序級別的併發限制利用率進行觀測,按 `priority_level` 細分。此利用率是(佔用座位數)/(併發限制)的比例。此指標考慮所有請求(除了 WATCH 請求)的執行的所有階段(正常階段和寫入結束時為相應通知工作而進行的額外延遲);對於 WATCH 請求,它僅考慮傳遞預先存在物件通知的初始階段。向量中的每個直方圖也用 `phase: executing` 標記(等待階段沒有座位限制)。

  • `apiserver_flowcontrol_request_queue_length_after_enqueue` 是一個直方圖向量,表示佇列的佇列長度,按 `priority_level` 和 `flow_schema` 細分,由排隊請求取樣。每個排隊請求都會為其直方圖貢獻一個樣本,報告請求新增後佇列的長度。請注意,這會產生與無偏調查不同的統計資料。

  • `apiserver_flowcontrol_request_concurrency_limit` 與 `apiserver_flowcontrol_nominal_limit_seats` 相同。在優先順序級別之間引入併發借用之前,這始終等於 `apiserver_flowcontrol_current_limit_seats`(它不存在作為獨立指標)。

  • `apiserver_flowcontrol_lower_limit_seats` 是一個計量向量,儲存每個優先順序級別動態併發限制的下限。

  • `apiserver_flowcontrol_upper_limit_seats` 是一個計量向量,儲存每個優先順序級別動態併發限制的上限。

  • `apiserver_flowcontrol_demand_seats` 是一個直方圖向量,每納秒末對每個優先順序級別(座位需求)/(名義併發限制)的比率進行計數。優先順序級別的座位需求是排隊請求和處於執行初始階段的請求中,請求在初始和最終執行階段佔用的最大座位數之和。

  • `apiserver_flowcontrol_demand_seats_high_watermark` 是一個計量向量,為每個優先順序級別儲存上次併發借用調整期間觀察到的最大座位需求。

  • `apiserver_flowcontrol_demand_seats_average` 是一個計量向量,為每個優先順序級別儲存上次併發借用調整期間觀察到的時間加權平均座位需求。

  • `apiserver_flowcontrol_demand_seats_stdev` 是一個計量向量,為每個優先順序級別儲存上次併發借用調整期間觀察到的座位需求的時間加權總體標準差。

  • `apiserver_flowcontrol_demand_seats_smoothed` 是一個計量向量,為每個優先順序級別儲存上次併發調整時確定的平滑包絡座位需求。

  • `apiserver_flowcontrol_target_seats` 是一個計量向量,為每個優先順序級別儲存借用分配問題中的併發目標。

  • `apiserver_flowcontrol_seat_fair_frac` 是一個計量,儲存上次借用調整中確定的公平分配分數。

  • `apiserver_flowcontrol_current_limit_seats` 是一個計量向量,為每個優先順序級別儲存上次調整中派生的動態併發限制。

  • `apiserver_flowcontrol_request_execution_seconds` 是一個直方圖向量,表示請求實際執行的時間,按 `flow_schema` 和 `priority_level` 細分。

  • `apiserver_flowcontrol_watch_count_samples` 是一個直方圖向量,表示與給定寫入相關的活動 WATCH 請求的數量,按 `flow_schema` 和 `priority_level` 細分。

  • `apiserver_flowcontrol_work_estimated_seats` 是一個直方圖向量,表示與請求相關的估計座位數(執行的初始階段和最終階段的最大值),按 `flow_schema` 和 `priority_level` 細分。

  • `apiserver_flowcontrol_request_dispatch_no_accommodation_total` 是一個計數器向量,表示原則上可能導致請求被分派但由於缺乏可用併發而未分派的事件數量,按 `flow_schema` 和 `priority_level` 細分。

  • `apiserver_flowcontrol_epoch_advance_total` 是一個計數器向量,表示將優先順序級別的進度計量器向後跳轉以避免數值溢位的嘗試次數,按 `priority_level` 和 `success` 分組。

使用 API 優先順序和公平性的最佳實踐

當給定優先順序級別超過其允許的併發量時,請求可能會經歷增加的延遲,或者被 HTTP 429(請求過多)錯誤拒絕。為了防止 APF 的這些副作用,您可以修改工作負載或調整 APF 設定,以確保有足夠的座位來處理您的請求。

要檢測請求是否因 APF 而被拒絕,請檢查以下指標:

  • apiserver_flowcontrol_rejected_requests_total:每個 FlowSchema 和 PriorityLevelConfiguration 被拒絕的請求總數。
  • apiserver_flowcontrol_current_inqueue_requests:每個 FlowSchema 和 PriorityLevelConfiguration 當前排隊的請求數量。
  • apiserver_flowcontrol_request_wait_duration_seconds:排隊等待請求的額外延遲。
  • apiserver_flowcontrol_priority_level_seat_utilization:每個 PriorityLevelConfiguration 的座位利用率。

工作負載修改

為了防止請求因 APF 而排隊增加延遲或被拒絕,您可以透過以下方式最佳化請求:

  • 降低請求執行的速率。在固定時間內較少的請求將導致在給定時間需要較少的座位。
  • 避免同時發出大量昂貴的請求。請求可以最佳化為使用更少的座位或具有更低的延遲,以便這些請求佔用座位的時間更短。列表請求可能佔用超過 1 個座位,具體取決於請求期間獲取的物件數量。限制列表請求中檢索的物件數量,例如透過使用分頁,將在更短的時間內使用更少的總座位。此外,用 watch 請求替換列表請求將需要更低的併發份額,因為 watch 請求在其初始突發通知期間僅佔用 1 個座位。如果使用 1.27 及更高版本中的流式列表,watch 請求將在其初始突發通知期間佔用與列表請求相同的座位數,因為必須流式傳輸整個集合的狀態。請注意,在兩種情況下,watch 請求在此初始階段之後都不會佔用任何座位。

請記住,APF 引起的排隊或被拒絕的請求可能是由請求數量增加或現有請求延遲增加引起的。例如,如果通常需要 1 秒執行的請求開始需要 60 秒,則 APF 可能會開始拒絕請求,因為請求由於延遲增加而佔用座位的時間比正常情況更長。如果 APF 在工作負載沒有顯著變化的情況下開始拒絕跨多個優先順序級別的請求,則可能是控制平面效能存在潛在問題,而不是工作負載或 APF 設定的問題。

優先順序和公平性設定

您還可以修改預設的 FlowSchema 和 PriorityLevelConfiguration 物件,或者建立這些型別的新物件,以更好地適應您的工作負載。

APF 設定可以修改為:

  • 為高優先順序請求提供更多座位。
  • 隔離非必要或昂貴的請求,這些請求如果與其他流共享併發級別,則會耗盡該併發級別。

為高優先順序請求提供更多座位

  1. 如果可能,可以透過增加 `max-requests-inflight` 和 `max-mutating-requests-inflight` 標誌的值來增加特定 `kube-apiserver` 所有優先順序級別的可用座位數。或者,橫向擴充套件 `kube-apiserver` 例項的數量將增加叢集中每個優先順序級別的總併發量,前提是請求的負載均衡足夠。
  2. 您可以建立一個新的 FlowSchema,它引用一個具有較大併發級別的 PriorityLevelConfiguration。這個新的 PriorityLevelConfiguration 可以是現有級別,也可以是一個擁有自己名義併發份額的新級別。例如,可以引入一個新的 FlowSchema,將您的請求的 PriorityLevelConfiguration 從 global-default 更改為 workload-low,以增加您使用者可用的座位數量。建立一個新的 PriorityLevelConfiguration 將減少指定給現有級別的座位數量。請注意,編輯預設的 FlowSchema 或 PriorityLevelConfiguration 需要將 `apf.kubernetes.io/autoupdate-spec` 註解設定為 false。
  3. 您還可以增加為高優先順序請求提供服務的 PriorityLevelConfiguration 的 NominalConcurrencyShares。或者,對於 1.26 及更高版本,您可以增加競爭優先順序級別的 LendablePercent,以便給定的優先順序級別擁有更高的可借用座位池。

隔離非必要請求,使其不耗盡其他流

為了進行請求隔離,您可以建立一個 FlowSchema,其主體匹配發出這些請求的使用者,或者建立一個匹配請求內容(對應於 resourceRules)的 FlowSchema。接下來,您可以將此 FlowSchema 對映到一個具有少量席位的 PriorityLevelConfiguration。

例如,假設來自 default 名稱空間中執行的 Pods 的列表事件請求每個使用 10 個座位並執行 1 分鐘。為了防止這些昂貴的請求影響使用現有服務帳戶 FlowSchema 的其他 Pod 的請求,您可以應用以下 FlowSchema 來隔離這些列表呼叫與其他請求。

用於隔離列表事件請求的示例 FlowSchema 物件

apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
  name: list-events-default-service-account
spec:
  distinguisherMethod:
    type: ByUser
  matchingPrecedence: 8000
  priorityLevelConfiguration:
    name: catch-all
  rules:
    - resourceRules:
      - apiGroups:
          - '*'
        namespaces:
          - default
        resources:
          - events
        verbs:
          - list
      subjects:
        - kind: ServiceAccount
          serviceAccount:
            name: default
            namespace: default
  • 此 FlowSchema 捕獲預設名稱空間中由預設服務帳戶進行的所有列表事件呼叫。匹配優先順序 8000 低於現有 `service-accounts` FlowSchema 使用的 9000 值,因此這些列表事件呼叫將匹配 `list-events-default-service-account` 而不是 `service-accounts`。
  • 全捕獲 PriorityLevelConfiguration 用於隔離這些請求。全捕獲優先順序級別具有非常小的併發份額,並且不排隊請求。

下一步

最後修改時間:2024 年 7 月 2 日下午 1:35(太平洋標準時間):修復拼寫錯誤 (856c384387)