Kubernetes API優(yōu)先級(jí)和公平性

2022-05-27 17:15 更新

API 優(yōu)先級(jí)和公平性

FEATURE STATE: Kubernetes v1.20 [beta]

對(duì)于集群管理員來(lái)說(shuō),控制 Kubernetes API 服務(wù)器在過(guò)載情況下的行為是一項(xiàng)關(guān)鍵任務(wù)。 kube-apiserver 有一些控件(例如:命令行標(biāo)志 ?--max-requests-inflight? 和 ?--max-mutating-requests-inflight? ), 可以限制將要接受的未處理的請(qǐng)求,從而防止過(guò)量請(qǐng)求入站,潛在導(dǎo)致 API 服務(wù)器崩潰。 但是這些標(biāo)志不足以保證在高流量期間,最重要的請(qǐng)求仍能被服務(wù)器接受。

API 優(yōu)先級(jí)和公平性(APF)是一種替代方案,可提升上述最大并發(fā)限制。 APF 以更細(xì)粒度的方式對(duì)請(qǐng)求進(jìn)行分類(lèi)和隔離。 它還引入了空間有限的排隊(duì)機(jī)制,因此在非常短暫的突發(fā)情況下,API 服務(wù)器不會(huì)拒絕任何請(qǐng)求。 通過(guò)使用公平排隊(duì)技術(shù)從隊(duì)列中分發(fā)請(qǐng)求,這樣, 一個(gè)行為不佳的 控制器 就不會(huì)餓死其他控制器(即使優(yōu)先級(jí)相同)。

本功能特性在設(shè)計(jì)上期望其能與標(biāo)準(zhǔn)控制器一起工作得很好; 這類(lèi)控制器使用通知組件(Informers)獲得信息并對(duì) API 請(qǐng)求的失效作出反應(yīng), 在處理失效時(shí)能夠執(zhí)行指數(shù)型回退。其他客戶(hù)端也以類(lèi)似方式工作。

Caution: 屬于“長(zhǎng)時(shí)間運(yùn)行”類(lèi)型的請(qǐng)求(主要是 watch)不受 API 優(yōu)先級(jí)和公平性過(guò)濾器的約束。 如果未啟用 APF 特性,即便設(shè)置 ?--max-requests-inflight? 標(biāo)志,該類(lèi)請(qǐng)求也不受約束。

啟用/禁用 API 優(yōu)先級(jí)和公平性 

API 優(yōu)先級(jí)與公平性(APF)特性由特性門(mén)控控制,默認(rèn)情況下啟用。 有關(guān)特性門(mén)控的一般性描述以及如何啟用和禁用特性門(mén)控, 請(qǐng)參見(jiàn)特性門(mén)控。 APF 的特性門(mén)控稱(chēng)為 ?APIPriorityAndFairness?。 此特性也與某個(gè) API 組 相關(guān): (a) ?v1alpha1 ?版本,默認(rèn)被禁用; (b) ?v1beta1 ?和 ?v1beta2 ?版本,默認(rèn)被啟用。 你可以在啟動(dòng) ?kube-apiserver? 時(shí),添加以下命令行標(biāo)志來(lái)禁用此功能門(mén)控及 API Beta 組:

kube-apiserver \
--feature-gates=APIPriorityAndFairness=false \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta1=false,flowcontrol.apiserver.k8s.io/v1beta2=false \
  # ...其他配置不變 

或者,你也可以通過(guò) ?--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true? 啟用 API 組的 v1alpha1 版本。

命令行標(biāo)志 ?--enable-priority-fairness=false? 將徹底禁用 APF 特性,即使其他標(biāo)志啟用它也是無(wú)效。

概念 

APF 特性包含幾個(gè)不同的功能。 傳入的請(qǐng)求通過(guò) FlowSchema 按照其屬性分類(lèi),并分配優(yōu)先級(jí)。 每個(gè)優(yōu)先級(jí)維護(hù)自定義的并發(fā)限制,加強(qiáng)了隔離度,這樣不同優(yōu)先級(jí)的請(qǐng)求,就不會(huì)相互餓死。 在同一個(gè)優(yōu)先級(jí)內(nèi),公平排隊(duì)算法可以防止來(lái)自不同 flow 的請(qǐng)求相互餓死。 該算法將請(qǐng)求排隊(duì),通過(guò)排隊(duì)機(jī)制,防止在平均負(fù)載較低時(shí),通信量突增而導(dǎo)致請(qǐng)求失敗。

優(yōu)先級(jí) 

如果未啟用 APF,API 服務(wù)器中的整體并發(fā)量將受到 ?kube-apiserver? 的參數(shù) ?--max-requests-inflight? 和 ?--max-mutating-requests-inflight? 的限制。 啟用 APF 后,將對(duì)這些參數(shù)定義的并發(fā)限制進(jìn)行求和,然后將總和分配到一組可配置的 優(yōu)先級(jí) 中。 每個(gè)傳入的請(qǐng)求都會(huì)分配一個(gè)優(yōu)先級(jí);每個(gè)優(yōu)先級(jí)都有各自的配置,設(shè)定允許分發(fā)的并發(fā)請(qǐng)求數(shù)。

例如,默認(rèn)配置包括針對(duì)領(lǐng)導(dǎo)者選舉請(qǐng)求、內(nèi)置控制器請(qǐng)求和 Pod 請(qǐng)求都單獨(dú)設(shè)置優(yōu)先級(jí)。 這表示即使異常的 Pod 向 API 服務(wù)器發(fā)送大量請(qǐng)求,也無(wú)法阻止領(lǐng)導(dǎo)者選舉或內(nèi)置控制器的操作執(zhí)行成功。

排隊(duì) 

即使在同一優(yōu)先級(jí)內(nèi),也可能存在大量不同的流量源。 在過(guò)載情況下,防止一個(gè)請(qǐng)求流餓死其他流是非常有價(jià)值的 (尤其是在一個(gè)較為常見(jiàn)的場(chǎng)景中,一個(gè)有故障的客戶(hù)端會(huì)瘋狂地向 kube-apiserver 發(fā)送請(qǐng)求, 理想情況下,這個(gè)有故障的客戶(hù)端不應(yīng)對(duì)其他客戶(hù)端產(chǎn)生太大的影響)。 公平排隊(duì)算法在處理具有相同優(yōu)先級(jí)的請(qǐng)求時(shí),實(shí)現(xiàn)了上述場(chǎng)景。 每個(gè)請(qǐng)求都被分配到某個(gè) 流 中,該 流 由對(duì)應(yīng)的 FlowSchema 的名字加上一個(gè) 流區(qū)分項(xiàng)(Flow Distinguisher) 來(lái)標(biāo)識(shí)。 這里的流區(qū)分項(xiàng)可以是發(fā)出請(qǐng)求的用戶(hù)、目標(biāo)資源的名稱(chēng)空間或什么都不是。 系統(tǒng)嘗試為不同流中具有相同優(yōu)先級(jí)的請(qǐng)求賦予近似相等的權(quán)重。 要啟用對(duì)不同實(shí)例的不同處理方式,多實(shí)例的控制器要分別用不同的用戶(hù)名來(lái)執(zhí)行身份認(rèn)證。

將請(qǐng)求劃分到流中之后,APF 功能將請(qǐng)求分配到隊(duì)列中。 分配時(shí)使用一種稱(chēng)為 混洗分片(Shuffle-Sharding) 的技術(shù)。 該技術(shù)可以相對(duì)有效地利用隊(duì)列隔離低強(qiáng)度流與高強(qiáng)度流。

排隊(duì)算法的細(xì)節(jié)可針對(duì)每個(gè)優(yōu)先等級(jí)進(jìn)行調(diào)整,并允許管理員在內(nèi)存占用、 公平性(當(dāng)總流量超標(biāo)時(shí),各個(gè)獨(dú)立的流將都會(huì)取得進(jìn)展)、 突發(fā)流量的容忍度以及排隊(duì)引發(fā)的額外延遲之間進(jìn)行權(quán)衡。

豁免請(qǐng)求 

某些特別重要的請(qǐng)求不受制于此特性施加的任何限制。這些豁免可防止不當(dāng)?shù)牧骺嘏渲猛耆?nbsp;API 服務(wù)器。

資源 

流控 API 涉及兩種資源。 PriorityLevelConfigurations 定義隔離類(lèi)型和可處理的并發(fā)預(yù)算量,還可以微調(diào)排隊(duì)行為。  FlowSchemas 用于對(duì)每個(gè)入站請(qǐng)求進(jìn)行分類(lèi),并與一個(gè) PriorityLevelConfigurations 相匹配。 此外同一 API 組還有一個(gè) ?v1alpha1 ?版本,其中包含語(yǔ)法和語(yǔ)義都相同的資源類(lèi)別。

PriorityLevelConfiguration 

一個(gè) PriorityLevelConfiguration 表示單個(gè)隔離類(lèi)型。每個(gè) PriorityLevelConfigurations 對(duì)未完成的請(qǐng)求數(shù)有各自的限制,對(duì)排隊(duì)中的請(qǐng)求數(shù)也有限制。

PriorityLevelConfigurations 的并發(fā)限制不是指定請(qǐng)求絕對(duì)數(shù)量,而是在“并發(fā)份額”中指定。 API 服務(wù)器的總并發(fā)量限制通過(guò)這些份額按例分配到現(xiàn)有 PriorityLevelConfigurations 中。 集群管理員可以更改 ?--max-requests-inflight? (或 ?--max-mutating-requests-inflight? )的值, 再重新啟動(dòng) ?kube-apiserver? 來(lái)增加或減小服務(wù)器的總流量, 然后所有的 PriorityLevelConfigurations 將看到其最大并發(fā)增加(或減少)了相同的比例。

Caution: 啟用 APF 功能后,服務(wù)器的總并發(fā)量限制將設(shè)置為 ?--max-requests-inflight? 和 ?--max-mutating-requests-inflight? 之和。 可變請(qǐng)求和不可變請(qǐng)求之間不再有任何區(qū)別; 如果對(duì)于某種資源,你需要區(qū)別對(duì)待不同請(qǐng)求,請(qǐng)創(chuàng)建不同的 FlowSchema 分別匹配可變請(qǐng)求和不可變請(qǐng)求。

當(dāng)入站請(qǐng)求的數(shù)量大于分配的 PriorityLevelConfigurations 中允許的并發(fā)級(jí)別時(shí), ?type ?字段將確定對(duì)額外請(qǐng)求的處理方式。 ?Reject ?類(lèi)型,表示多余的流量將立即被 HTTP 429(請(qǐng)求過(guò)多)錯(cuò)誤所拒絕。 ?Queue ?類(lèi)型,表示對(duì)超過(guò)閾值的請(qǐng)求進(jìn)行排隊(duì),將使用閾值分片和公平排隊(duì)技術(shù)來(lái)平衡請(qǐng)求流之間的進(jìn)度。

公平排隊(duì)算法支持通過(guò)排隊(duì)配置對(duì)優(yōu)先級(jí)微調(diào):

  • ?queues ?遞增能減少不同流之間的沖突概率,但代價(jià)是增加了內(nèi)存使用量。 值為 1 時(shí),會(huì)禁用公平排隊(duì)邏輯,但仍允許請(qǐng)求排隊(duì)。
  • ?queueLengthLimit ?遞增可以在不丟棄任何請(qǐng)求的情況下支撐更大的突發(fā)流量, 但代價(jià)是增加了等待時(shí)間和內(nèi)存使用量。
  • 修改 ?handSize ?允許你調(diào)整過(guò)載情況下不同流之間的沖突概率以及單個(gè)流可用的整體并發(fā)性。
Note: 較大的 ?handSize ?使兩個(gè)單獨(dú)的流程發(fā)生碰撞的可能性較?。ㄒ虼?,一個(gè)流可以餓死另一個(gè)流), 但是更有可能的是少數(shù)流可以控制 apiserver。 較大的 ?handSize ?還可能增加單個(gè)高并發(fā)流的延遲量。 單個(gè)流中可能排隊(duì)的請(qǐng)求的最大數(shù)量為 ?handSize * queueLengthLimit? 。

下表顯示了有趣的隨機(jī)分片配置集合, 每行顯示給定的老鼠(低強(qiáng)度流)被不同數(shù)量的大象擠壓(高強(qiáng)度流)的概率。 表來(lái)源請(qǐng)參閱: https://play.golang.org/p/Gi0PLgVHiUg

隨機(jī)分片 隊(duì)列數(shù) 1 個(gè)大象 4 個(gè)大象 16 個(gè)大象
12 32 4.428838398950118e-09 0.11431348830099144 0.9935089607656024
10 32 1.550093439632541e-08 0.0626479840223545 0.9753101519027554
10 64 6.601827268370426e-12 0.00045571320990370776 0.49999929150089345
9 64 3.6310049976037345e-11 0.00045501212304112273 0.4282314876454858
8 64 2.25929199850899e-10 0.0004886697053040446 0.35935114681123076
8 128 6.994461389026097e-13 3.4055790161620863e-06 0.02746173137155063
7 128 1.0579122850901972e-11 6.960839379258192e-06 0.02406157386340147
7 256 7.597695465552631e-14 6.728547142019406e-08 0.0006709661542533682
6 256 2.7134626662687968e-12 2.9516464018476436e-07 0.0008895654642000348
6 512 4.116062922897309e-14 4.982983350480894e-09 2.26025764343413e-05
6 1024 6.337324016514285e-16 8.09060164312957e-11 4.517408062903668e-07

FlowSchema 

FlowSchema 匹配一些入站請(qǐng)求,并將它們分配給優(yōu)先級(jí)。 每個(gè)入站請(qǐng)求都會(huì)對(duì)所有 FlowSchema 測(cè)試是否匹配, 首先從 ?matchingPrecedence ?數(shù)值最低的匹配開(kāi)始(我們認(rèn)為這是邏輯上匹配度最高), 然后依次進(jìn)行,直到首個(gè)匹配出現(xiàn)。

Caution: 對(duì)一個(gè)請(qǐng)求來(lái)說(shuō),只有首個(gè)匹配的 FlowSchema 才有意義。 如果一個(gè)入站請(qǐng)求與多個(gè) FlowSchema 匹配,則將基于 ?matchingPrecedence ?值最高的請(qǐng)求進(jìn)行篩選。 如果一個(gè)請(qǐng)求匹配多個(gè) FlowSchema 且 ?matchingPrecedence ?的值相同,則按 ?name ?的字典序選擇最小, 但是最好不要依賴(lài)它,而是確保不存在兩個(gè) FlowSchema 具有相同的 ?matchingPrecedence ?值。

當(dāng)給定的請(qǐng)求與某個(gè) FlowSchema 的 ?rules ?的其中一條匹配,那么就認(rèn)為該請(qǐng)求與該 FlowSchema 匹配。 判斷規(guī)則與該請(qǐng)求是否匹配,不僅要求該條規(guī)則的 ?subjects ?字段至少存在一個(gè)與該請(qǐng)求相匹配, 而且要求該條規(guī)則的 ?resourceRules ?或 ?nonResourceRules ?(取決于傳入請(qǐng)求是針對(duì)資源URL還是非資源URL)字段至少存在一個(gè)與該請(qǐng)求相匹配。

對(duì)于 ?subjects ?中的 ?name ?字段和資源和非資源規(guī)則的 ?verbs?,?apiGroups?,?resources?,?namespaces ?和 ?nonResourceURLs ?字段, 可以指定通配符 ?*? 來(lái)匹配任意值,從而有效地忽略該字段。

FlowSchema 的 ?distinguisherMethod.type? 字段決定了如何把與該模式匹配的請(qǐng)求分散到各個(gè)流中。 可能是 ?ByUser ?,在這種情況下,一個(gè)請(qǐng)求用戶(hù)將無(wú)法餓死其他容量的用戶(hù); 或者是 ?ByNamespace ?,在這種情況下,一個(gè)名稱(chēng)空間中的資源請(qǐng)求將無(wú)法餓死其它名稱(chēng)空間的資源請(qǐng)求; 或者它可以為空(或者可以完全省略 ?distinguisherMethod?), 在這種情況下,與此 FlowSchema 匹配的請(qǐng)求將被視為單個(gè)流的一部分。 資源和你的特定環(huán)境決定了如何選擇正確一個(gè) FlowSchema。

默認(rèn)值 

每個(gè) kube-apiserver 會(huì)維護(hù)兩種類(lèi)型的 APF 配置對(duì)象:強(qiáng)制的(Mandatory)和建議的(Suggested)。

強(qiáng)制的配置對(duì)象

有四種強(qiáng)制的配置對(duì)象對(duì)應(yīng)內(nèi)置的守護(hù)行為。這里的行為是服務(wù)器在還未創(chuàng)建對(duì)象之前就具備的行為, 而當(dāng)這些對(duì)象存在時(shí),其規(guī)約反映了這類(lèi)行為。四種強(qiáng)制的對(duì)象如下:

  • 強(qiáng)制的 ?exempt ?優(yōu)先級(jí)用于完全不受流控限制的請(qǐng)求:它們總是立刻被分發(fā)。 強(qiáng)制的 ?exempt ?FlowSchema 把 ?system:masters? 組的所有請(qǐng)求都?xì)w入該優(yōu)先級(jí)。 如果合適,你可以定義新的 FlowSchema,將其他請(qǐng)求定向到該優(yōu)先級(jí)。
  • 強(qiáng)制的 ?catch-all? 優(yōu)先級(jí)與強(qiáng)制的 ?catch-all? FlowSchema 結(jié)合使用, 以確保每個(gè)請(qǐng)求都分類(lèi)。一般而言,你不應(yīng)該依賴(lài)于 ?catch-all? 的配置, 而應(yīng)適當(dāng)?shù)貏?chuàng)建自己的 ?catch-all? FlowSchema 和 PriorityLevelConfiguration (或使用默認(rèn)安裝的 ?global-default? 配置)。 因?yàn)檫@一優(yōu)先級(jí)不是正常場(chǎng)景下要使用的,?catch-all? 優(yōu)先級(jí)的并發(fā)度份額很小, 并且不會(huì)對(duì)請(qǐng)求進(jìn)行排隊(duì)。

建議的配置對(duì)象

建議的 FlowSchema 和 PriorityLevelConfiguration 包含合理的默認(rèn)配置。 你可以修改這些對(duì)象或者根據(jù)需要?jiǎng)?chuàng)建新的配置對(duì)象。如果你的集群可能承受較重負(fù)載, 那么你就要考慮哪種配置最合適。

建議的配置把請(qǐng)求分為六個(gè)優(yōu)先級(jí):

  • ?node-high? 優(yōu)先級(jí)用于來(lái)自節(jié)點(diǎn)的健康狀態(tài)更新。
  • ?system ?優(yōu)先級(jí)用于 ?system:nodes? 組(即 kubelet)的與健康狀態(tài)更新無(wú)關(guān)的請(qǐng)求; kubelets 必須能連上 API 服務(wù)器,以便工作負(fù)載能夠調(diào)度到其上。
  • ?leader-election? 優(yōu)先級(jí)用于內(nèi)置控制器的領(lǐng)導(dǎo)選舉的請(qǐng)求 (特別是來(lái)自 ?kube-system? 名稱(chēng)空間中 ?system:kube-controller-manager? 和 ?system:kube-scheduler? 用戶(hù)和服務(wù)賬號(hào),針對(duì) ?endpoints?、?configmaps ?或 ?leases ?的請(qǐng)求)。 將這些請(qǐng)求與其他流量相隔離非常重要,因?yàn)轭I(lǐng)導(dǎo)者選舉失敗會(huì)導(dǎo)致控制器發(fā)生故障并重新啟動(dòng), 這反過(guò)來(lái)會(huì)導(dǎo)致新啟動(dòng)的控制器在同步信息時(shí),流量開(kāi)銷(xiāo)更大。
  • ?workload-high? 優(yōu)先級(jí)用于內(nèi)置控制器的其他請(qǐng)求。
  • ?workload-low? 優(yōu)先級(jí)用于來(lái)自所有其他服務(wù)帳戶(hù)的請(qǐng)求,通常包括來(lái)自 Pod 中運(yùn)行的控制器的所有請(qǐng)求。
  • ?global-default? 優(yōu)先級(jí)可處理所有其他流量,例如:非特權(quán)用戶(hù)運(yùn)行的交互式 ?kubectl ?命令。

建議的 FlowSchema 用來(lái)將請(qǐng)求導(dǎo)向上述的優(yōu)先級(jí)內(nèi),這里不再一一列舉。

強(qiáng)制的與建議的配置對(duì)象的維護(hù)

每個(gè) ?kube-apiserver? 都獨(dú)立地維護(hù)其強(qiáng)制的與建議的配置對(duì)象, 這一維護(hù)操作既是服務(wù)器的初始行為,也是其周期性操作的一部分。 因此,當(dāng)存在不同版本的服務(wù)器時(shí),如果各個(gè)服務(wù)器對(duì)于配置對(duì)象中的合適內(nèi)容有不同意見(jiàn), 就可能出現(xiàn)抖動(dòng)。

每個(gè) ?kube-apiserver? 都會(huì)對(duì)強(qiáng)制的與建議的配置對(duì)象執(zhí)行初始的維護(hù)操作, 之后(每分鐘)對(duì)這些對(duì)象執(zhí)行周期性的維護(hù)。

對(duì)于強(qiáng)制的配置對(duì)象,維護(hù)操作包括確保對(duì)象存在并且包含合適的規(guī)約(如果存在的話)。 服務(wù)器會(huì)拒絕創(chuàng)建或更新與其守護(hù)行為不一致的規(guī)約。

對(duì)建議的配置對(duì)象的維護(hù)操作被設(shè)計(jì)為允許其規(guī)約被重載。刪除操作是不允許的, 維護(hù)操作期間會(huì)重建這類(lèi)配置對(duì)象。如果你不需要某個(gè)建議的配置對(duì)象, 你需要將它放在一邊,并讓其規(guī)約所產(chǎn)生的影響最小化。 對(duì)建議的配置對(duì)象而言,其維護(hù)方面的設(shè)計(jì)也支持在上線新的 ?kube-apiserver? 時(shí)完成自動(dòng)的遷移動(dòng)作,即便可能因?yàn)楫?dāng)前的服務(wù)器集合存在不同的版本而可能造成抖動(dòng)仍是如此。

對(duì)建議的配置對(duì)象的維護(hù)操作包括基于服務(wù)器建議的規(guī)約創(chuàng)建對(duì)象 (如果對(duì)象不存在的話)。反之,如果對(duì)象已經(jīng)存在,維護(hù)操作的行為取決于是否 ?kube-apiserver? 或者用戶(hù)在控制對(duì)象。如果 ?kube-apiserver? 在控制對(duì)象, 則服務(wù)器確保對(duì)象的規(guī)約與服務(wù)器所給的建議匹配,如果用戶(hù)在控制對(duì)象, 對(duì)象的規(guī)約保持不變。

關(guān)于誰(shuí)在控制對(duì)象這個(gè)問(wèn)題,首先要看對(duì)象上的 ?apf.kubernetes.io/autoupdate-spec? 注解。如果對(duì)象上存在這個(gè)注解,并且其取值為?true?,則 kube-apiserver 在控制該對(duì)象。如果存在這個(gè)注解,并且其取值為?false?,則用戶(hù)在控制對(duì)象。 如果這兩個(gè)條件都不滿足,則需要進(jìn)一步查看對(duì)象的 ?metadata.generation?。 如果該值為 1,則 kube-apiserver 控制對(duì)象,否則用戶(hù)控制對(duì)象。 這些規(guī)則是在 1.22 發(fā)行版中引入的,而對(duì) ?metadata.generation? 的考量是為了便于從之前較簡(jiǎn)單的行為遷移過(guò)來(lái)。希望控制建議的配置對(duì)象的用戶(hù)應(yīng)該將對(duì)象的 ?apf.kubernetes.io/autoupdate-spec? 注解設(shè)置為 ?false?。

對(duì)強(qiáng)制的或建議的配置對(duì)象的維護(hù)操作也包括確保對(duì)象上存在 ?apf.kubernetes.io/autoupdate-spec? 這一注解,并且其取值準(zhǔn)確地反映了是否 kube-apiserver 在控制著對(duì)象。

維護(hù)操作還包括刪除那些既非強(qiáng)制又非建議的配置,同時(shí)注解配置為 ?apf.kubernetes.io/autoupdate-spec=true? 的對(duì)象。

健康檢查并發(fā)豁免 

推薦配置沒(méi)有為本地 kubelet 對(duì) kube-apiserver 執(zhí)行健康檢查的請(qǐng)求進(jìn)行任何特殊處理 ——它們傾向于使用安全端口,但不提供憑據(jù)。 在推薦配置中,這些請(qǐng)求將分配 ?global-default? FlowSchema 和 ?global-default? 優(yōu)先級(jí), 這樣其他流量可以排除健康檢查。

如果添加以下 FlowSchema,健康檢查請(qǐng)求不受速率限制。

Caution: 進(jìn)行此更改后,任何敵對(duì)方都可以發(fā)送與此 FlowSchema 匹配的任意數(shù)量的健康檢查請(qǐng)求。 如果你有 Web 流量過(guò)濾器或類(lèi)似的外部安全機(jī)制保護(hù)集群的 API 服務(wù)器免受常規(guī)網(wǎng)絡(luò)流量的侵?jǐn)_, 則可以配置規(guī)則,阻止所有來(lái)自集群外部的健康檢查請(qǐng)求。
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
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

問(wèn)題診斷 

啟用了 APF 的 API 服務(wù)器,它每個(gè) HTTP 響應(yīng)都有兩個(gè)額外的 HTTP 頭: ?X-Kubernetes-PF-FlowSchema-UID? 和 ?X-Kubernetes-PF-PriorityLevel-UID?, 注意與請(qǐng)求匹配的 FlowSchema 和已分配的優(yōu)先級(jí)。 如果請(qǐng)求用戶(hù)沒(méi)有查看這些對(duì)象的權(quán)限,則這些 HTTP 頭中將不包含 API 對(duì)象的名稱(chēng), 因此在調(diào)試時(shí),你可以使用類(lèi)似如下的命令:

kubectl get flowschemas -o custom-columns="uid:{metadata.uid},name:{metadata.name}"
kubectl get prioritylevelconfigurations -o custom-columns="uid:{metadata.uid},name:{metadata.name}"             

來(lái)獲取 UID 到 FlowSchema 的名稱(chēng)和 UID 到 PriorityLevelConfigurations 的名稱(chēng)的映射。

可觀察性 

指標(biāo)

Note: 在 Kubernetes v1.20 之前的版本中,標(biāo)簽 ?flow_schema ?和 ?priority_level? 的名稱(chēng)有時(shí)被寫(xiě)作 ?flowSchema ?和 ?priorityLevel?,即存在不一致的情況。 如果你在運(yùn)行 Kubernetes v1.19 或者更早版本,你需要參考你所使用的集群 版本對(duì)應(yīng)的文檔。

當(dāng)你開(kāi)啟了 APF 后,kube-apiserver 會(huì)暴露額外指標(biāo)。 監(jiān)視這些指標(biāo)有助于判斷你的配置是否不當(dāng)?shù)叵拗屏酥匾髁浚?nbsp;或者發(fā)現(xiàn)可能會(huì)損害系統(tǒng)健康的,行為不良的工作負(fù)載。

  • ?apiserver_flowcontrol_rejected_requests_total ?是一個(gè)計(jì)數(shù)器向量, 記錄被拒絕的請(qǐng)求數(shù)量(自服務(wù)器啟動(dòng)以來(lái)累計(jì)值), 由標(biāo)簽 ?flow_chema?(表示與請(qǐng)求匹配的 FlowSchema),?priority_evel ?(表示分配給請(qǐng)?jiān)撉蟮膬?yōu)先級(jí))和 ?reason ?來(lái)區(qū)分。 ?reason ?標(biāo)簽將具有以下值之一:
    • ?queue-full? ,表明已經(jīng)有太多請(qǐng)求排隊(duì),
    • ?concurrency-limit?,表示將 PriorityLevelConfiguration 配置為 ?Reject ?而不是 ?Queue ?,或者
    • ?time-out?, 表示在其排隊(duì)時(shí)間超期的請(qǐng)求仍在隊(duì)列中。
  • ?apiserver_flowcontrol_dispatched_requests_total? 是一個(gè)計(jì)數(shù)器向量, 記錄開(kāi)始執(zhí)行的請(qǐng)求數(shù)量(自服務(wù)器啟動(dòng)以來(lái)的累積值), 由標(biāo)簽 ?flow_schema?(表示與請(qǐng)求匹配的 FlowSchema)和 ?priority_level?(表示分配給該請(qǐng)求的優(yōu)先級(jí))來(lái)區(qū)分。
  • ?apiserver_current_inqueue_requests ?是一個(gè)表向量, 記錄最近排隊(duì)請(qǐng)求數(shù)量的高水位線, 由標(biāo)簽 ?request_kind ?分組,標(biāo)簽的值為 ?mutating ?或 ?readOnly?。 這些高水位線表示在最近一秒鐘內(nèi)看到的最大數(shù)字。 它們補(bǔ)充說(shuō)明了老的表向量 ?apiserver_current_inflight_requests ?(該量保存了最后一個(gè)窗口中,正在處理的請(qǐng)求數(shù)量的高水位線)。
  • ?apiserver_flowcontrol_read_vs_write_request_count_samples ?是一個(gè)直方圖向量, 記錄當(dāng)前請(qǐng)求數(shù)量的觀察值, 由標(biāo)簽 ?phase?(取值為 ?waiting ?和 ?executing?)和 ?request_kind ?(取值 ?mutating ?和 ?readOnly?)拆分。定期以高速率觀察該值。
  • ?apiserver_flowcontrol_read_vs_write_request_count_watermarks ?是一個(gè)直方圖向量, 記錄請(qǐng)求數(shù)量的高/低水位線, 由標(biāo)簽 ?phase?(取值為 ?waiting ?和 ?executing?)和 ?request_kind ?(取值為 ?mutating ?和 ?readOnly?)拆分;標(biāo)簽 ?mark ?取值為 ?high ?和 ?low ?。 ?apiserver_flowcontrol_read_vs_write_request_count_samples ?向量觀察到有值新增, 則該向量累積。這些水位線顯示了樣本值的范圍。
  • ?apiserver_flowcontrol_current_inqueue_requests ?是一個(gè)表向量, 記錄包含排隊(duì)中的(未執(zhí)行)請(qǐng)求的瞬時(shí)數(shù)量, 由標(biāo)簽 ?priorityLevel ?和 ?flowSchema ?拆分。
  • ?apiserver_flowcontrol_current_executing_requests ?是一個(gè)表向量, 記錄包含執(zhí)行中(不在隊(duì)列中等待)請(qǐng)求的瞬時(shí)數(shù)量, 由標(biāo)簽 ?priority_level ?和 ?flow_schema ?進(jìn)一步區(qū)分。
  • ?apiserver_flowcontrol_request_concurrency_in_use ?是一個(gè)規(guī)范向量, 包含占用座位的瞬時(shí)數(shù)量,由標(biāo)簽 ?priority_level ?和 ?flow_schema ?進(jìn)一步區(qū)分。
  • ?apiserver_flowcontrol_priority_level_request_count_samples ?是一個(gè)直方圖向量, 記錄當(dāng)前請(qǐng)求的觀測(cè)值,由標(biāo)簽 ?phase?(取值為?waiting ?和 ?executing?)和 ?priority_level ?進(jìn)一步區(qū)分。 每個(gè)直方圖都會(huì)定期進(jìn)行觀察,直到相關(guān)類(lèi)別的最后活動(dòng)為止。觀察頻率高。
  • ?apiserver_flowcontrol_priority_level_request_count_watermarks ?是一個(gè)直方圖向量, 記錄請(qǐng)求數(shù)的高/低水位線,由標(biāo)簽 ?phase?(取值為 ?waiting ?和 ?executing?)和 ?priority_level ?拆分; 標(biāo)簽 ?mark ?取值為 ?high ?和 ?low ?。 ?apiserver_flowcontrol_priority_level_request_count_samples ?向量觀察到有值新增, 則該向量累積。這些水位線顯示了樣本值的范圍。
  • ?apiserver_flowcontrol_request_queue_length_after_enqueue ?是一個(gè)直方圖向量, 記錄請(qǐng)求隊(duì)列的長(zhǎng)度,由標(biāo)簽 ?priority_level ?和 ?flow_schema ?進(jìn)一步區(qū)分。 每個(gè)排隊(duì)中的請(qǐng)求都會(huì)為其直方圖貢獻(xiàn)一個(gè)樣本,并在添加請(qǐng)求后立即上報(bào)隊(duì)列的長(zhǎng)度。 請(qǐng)注意,這樣產(chǎn)生的統(tǒng)計(jì)數(shù)據(jù)與無(wú)偏調(diào)查不同。
Note: 直方圖中的離群值在這里表示單個(gè)流(即,一個(gè)用戶(hù)或一個(gè)名稱(chēng)空間的請(qǐng)求, 具體取決于配置)正在瘋狂地向 API 服務(wù)器發(fā)請(qǐng)求,并受到限制。 相反,如果一個(gè)優(yōu)先級(jí)的直方圖顯示該優(yōu)先級(jí)的所有隊(duì)列都比其他優(yōu)先級(jí)的隊(duì)列長(zhǎng), 則增加 PriorityLevelConfigurations 的并發(fā)份額是比較合適的。
  • ?apiserver_flowcontrol_request_concurrency_limit ?是一個(gè)表向量, 記錄并發(fā)限制的計(jì)算值(基于 API 服務(wù)器的總并發(fā)限制和 PriorityLevelConfigurations 的并發(fā)份額),并按標(biāo)簽 ?priority_level ?進(jìn)一步區(qū)分。
  • ?apiserver_flowcontrol_request_wait_duration_seconds ?是一個(gè)直方圖向量, 記錄請(qǐng)求排隊(duì)的時(shí)間, 由標(biāo)簽 ?flow_schema?(表示與請(qǐng)求匹配的 FlowSchema ), ?priority_level?(表示分配該請(qǐng)求的優(yōu)先級(jí)) 和 ?execute?(表示請(qǐng)求是否開(kāi)始執(zhí)行)進(jìn)一步區(qū)分。

Note: 由于每個(gè) FlowSchema 總會(huì)給請(qǐng)求分配 PriorityLevelConfigurations, 因此你可以為一個(gè)優(yōu)先級(jí)添加所有 FlowSchema 的直方圖,以獲取分配給 該優(yōu)先級(jí)的請(qǐng)求的有效直方圖。

  • ?apiserver_flowcontrol_request_execution_seconds ?是一個(gè)直方圖向量, 記錄請(qǐng)求實(shí)際執(zhí)行需要花費(fèi)的時(shí)間, 由標(biāo)簽 ?flow_schema?(表示與請(qǐng)求匹配的 FlowSchema )和 ?priority_level?(表示分配給該請(qǐng)求的優(yōu)先級(jí))進(jìn)一步區(qū)分。

調(diào)試端點(diǎn) 

啟用 APF 特性后, kube-apiserver 會(huì)在其 HTTP/HTTPS 端口提供以下路徑:

  • ?/debug/api_priority_and_fairness/dump_priority_levels? —— 所有優(yōu)先級(jí)及其當(dāng)前狀態(tài)的列表。你可以這樣獲?。?/li>
    kubectl get --raw /debug/api_priority_and_fairness/dump_priority_levels
    

    輸出類(lèi)似于:

    PriorityLevelName, ActiveQueues, IsIdle, IsQuiescing, WaitingRequests, ExecutingRequests,
    workload-low,      0,            true,   false,       0,               0,
    global-default,    0,            true,   false,       0,               0,
    exempt,            <none>,       <none>, <none>,      <none>,          <none>,
    catch-all,         0,            true,   false,       0,               0,
    system,            0,            true,   false,       0,               0,
    leader-election,   0,            true,   false,       0,               0,
    workload-high,     0,            true,   false,       0,               0,
  • ?/debug/api_priority_and_fairness/dump_queues? —— 所有隊(duì)列及其當(dāng)前狀態(tài)的列表。 你可以這樣獲?。?/li>
    kubectl get --raw /debug/api_priority_and_fairness/dump_queues
    

    輸出類(lèi)似于:

    PriorityLevelName, Index,  PendingRequests, ExecutingRequests, VirtualStart,
    workload-high,     0,      0,               0,                 0.0000,
    workload-high,     1,      0,               0,                 0.0000,
    workload-high,     2,      0,               0,                 0.0000,
    ...
    leader-election,   14,     0,               0,                 0.0000,
    leader-election,   15,     0,               0,                 0.0000,
  • ?/debug/api_priority_and_fairness/dump_requests? ——當(dāng)前正在隊(duì)列中等待的所有請(qǐng)求的列表。 你可以這樣獲?。?/li>
    kubectl get --raw /debug/api_priority_and_fairness/dump_requests
    

    輸出類(lèi)似于:

    PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher,       ArriveTime,
    exempt,            <none>,         <none>,     <none>,              <none>,                <none>,
    system,            system-nodes,   12,         0,                   system:node:127.0.0.1, 2020-07-23T15:26:57.179170694Z,

    針對(duì)每個(gè)優(yōu)先級(jí)別,輸出中還包含一條虛擬記錄,對(duì)應(yīng)豁免限制。

    你可以使用以下命令獲得更詳細(xì)的清單:

    kubectl get --raw '/debug/api_priority_and_fairness/dump_requests?includeRequestDetails=1'
    

    輸出類(lèi)似于:

    PriorityLevelName, FlowSchemaName, QueueIndex, RequestIndexInQueue, FlowDistingsher,       ArriveTime,                     UserName,              Verb,   APIPath,                                                     Namespace, Name,   APIVersion, Resource, SubResource,
    system,            system-nodes,   12,         0,                   system:node:127.0.0.1, 2020-07-23T15:31:03.583823404Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,
    system,            system-nodes,   12,         1,                   system:node:127.0.0.1, 2020-07-23T15:31:03.594555947Z, system:node:127.0.0.1, create, /api/v1/namespaces/scaletest/configmaps,


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)