自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

添加K8S CPU limit會降低服務(wù)性能?

云計算 云原生
谷歌的最佳實(shí)踐告訴你,重要服務(wù)一定要配置 Guaranteed 的,這樣在資源不足的時候可以保證你的重要服務(wù)不被驅(qū)逐。

眾所周知,Kubernetes QOS 分為三個級別:

  • Guaranteed:Pod 里的每個容器都必須有內(nèi)存/CPU 限制和請求,而且值必須相等。如果一個容器只指明limit而未設(shè)定request,則request的值等于limit值。
  • Burstable:Pod 里至少有一個容器有內(nèi)存或者 CPU 請求且不滿足 Guarantee 等級的要求,即內(nèi)存/CPU 的值設(shè)置的不同。
  • BestEffort:容器必須沒有任何內(nèi)存或者 CPU 的限制或請求。

谷歌的最佳實(shí)踐告訴你,重要服務(wù)一定要配置 Guaranteed 的,這樣在資源不足的時候可以保證你的重要服務(wù)不被驅(qū)逐。

最佳實(shí)踐要求你這樣配置是從運(yùn)維和后期運(yùn)營的角度來說的,團(tuán)隊(duì)剛起步,不設(shè)置資源請求和限制的情況下基本可以正常工作,但隨著團(tuán)隊(duì)和項(xiàng)目的增長,您將開始遇到穩(wěn)定性問題。服務(wù)之間相互影響,這時候可能需要為服務(wù)添加限制,并且可以讓您免于遇到許多令人頭疼的問題。

這里我們應(yīng)該已經(jīng)清楚,通過遵循最佳實(shí)踐,使整個集群具有更大的靈活性和可靠性。

但是當(dāng)涉及到 CPU 限制時,事情就變得有趣了。CPU 是可壓縮資源。如果您的應(yīng)用開始達(dá)到 CPU 限制,Kubernetes 就會開始限制您的容器。這意味著 CPU 將受到人為限制,使您的應(yīng)用程序性能可能更差!

1. 為什么會這樣呢?

因?yàn)楫?dāng)你在容器編排器中設(shè)置硬 CPU 限制時,內(nèi)核使用完全公平調(diào)度程序 (CFS) Cgroup來強(qiáng)制執(zhí)行這些限制。CFS Cgroup 機(jī)制使用兩個設(shè)置來管理 CPU 分配:配額和周期。當(dāng)應(yīng)用程序在給定時間段內(nèi)使用超過其分配的 CPU 配額時,它會受到限制,直到下一個時間段。

cgroup 的所有 CPU 指標(biāo)都位于??/sys/fs/cgroup/cpu,cpuacct/<container>??. 配額和期間設(shè)置位于??cpu.cfs_quota_us??和中??cpu.cfs_period_us??。

您還可以查看限制指標(biāo) cpu.stat。在里面 cpu.stat 你會發(fā)現(xiàn):

  • nr_periods– cgroup 任何線程可運(yùn)行的周期數(shù)
  • nr_throttled– 應(yīng)用程序使用其全部配額并受到限制的可運(yùn)行周期數(shù)
  • throttled_time– 控制 cgroup 中各個線程的總時間

2. 舉個簡單的例子

單線程應(yīng)用程序在具有 cgroup 約束的 CPU 上運(yùn)行。此應(yīng)用程序需要 200 毫秒的處理時間來完成一個請求。不受約束,它的響應(yīng)看起來如下圖。

沒有配置限制的請求

現(xiàn)在,假設(shè)我們?yōu)閼?yīng)用程序分配了 0.4 CPU 的 CPU 限制。這意味著應(yīng)用程序每 100 毫秒周期獲得 40 毫秒的運(yùn)行時間——即使這些時間 CPU 沒有其他工作要做。200 毫秒的請求現(xiàn)在需要 440 毫秒才能完成。

配置限制的請求

這個時候你查看下所在容器路徑下的 cpu.stat throttled_time 你會發(fā)現(xiàn)被限制了 240ms(對于每 100 毫秒的周期,應(yīng)用程序只能運(yùn)行 40 毫秒,并被限制 60 毫秒。它已被限制了 4 個周期,因此 4 * 60 = 240 毫秒。)

換一個通俗點(diǎn)的說法,當(dāng)您要求 1 個 CPU 時,這意味著您的應(yīng)用程序每秒可以使用 1 個 CPU 內(nèi)核。如果它是一個單線程,它將能夠一直使用一個內(nèi)核。但是,如果它有 2 個線程,則每秒可以無限制地使用 2 個核心秒。因此,有了這個限制,它可以在 1/2 秒內(nèi)完全使用 2 個核心,然后會受到限制。(雖然這并不是真正以秒為單位來衡量的,實(shí)際是us,但我發(fā)現(xiàn)這樣更容易理解)。

看到這里,你可能會說,這只是一種約束,超出范圍的資源,就是不能使用,否則將被限制。

3. 是否存在不必要的限制

并沒有這么簡單,很多人反饋遭到了不必要的 cgroup 限制,甚至還沒有 CPU 上限,這里有激烈的討論:

  1. ????https://github.com/kubernetes/kubernetes/issues/67577????
  2. ????https://github.com/kubernetes/kubernetes/issues/51135????
  3. ????https://github.com/kubernetes/kubernetes/issues/70585????
  4. ????https://github.com/kubernetes/kubernetes/pull/75682????

運(yùn)行容器時要檢查的關(guān)鍵指標(biāo)是throttling. 這表明您的容器被限制的次數(shù)。我們發(fā)現(xiàn)很多容器無論 CPU 使用率是否接近極限都會受到限制。如下一個熱心網(wǎng)友反饋的案例:

在動畫中可以看到 CPU 限制設(shè)置為800m(0.8 個核心,80% 的核心),峰值使用率最高為200m(20% 的核心)??吹街?,我們可能會認(rèn)為我們有足夠的 CPU 讓服務(wù)在它節(jié)流之前運(yùn)行,對吧?. 現(xiàn)在看看這個:

即使 CPU 使用率低于 CPU 限制,您也會注意到發(fā)生了 CPU 限制。最大 CPU 使用率甚至沒有接近 CPU 限制。

限制就意味著服務(wù)性能下降和延遲增高。

4. 什么原因?qū)е碌哪兀?/span>

本質(zhì)上來說,這個問題是 linux 內(nèi)核導(dǎo)致,具體可以看下這個視頻:????https://www.youtube.com/watch?v=UE7QX98-kO0????

這個視頻大概意思是這樣的。

這里有一個多線程守護(hù)進(jìn)程的例子,它有兩個工作線程,每個工作線程都固定在自己的核心上。如下圖,第一個圖顯示了 cgroup 在一段時間內(nèi)的全局配額。這從 20ms 的配額開始,這與 0.2 CPU 相關(guān)。中間的圖表顯示分配給每個 CPU 隊(duì)列的配額,底部的圖表顯示實(shí)際工作線程在其 CPU 上運(yùn)行的時間。

在 10 毫秒:

  • Worker 1 收到了一個請求。
  • 一部分配額從全局配額轉(zhuǎn)移到 CPU 1 的每個 CPU 隊(duì)列。
  • Worker 1 需要 5ms 來處理和響應(yīng)請求。

在 17 毫秒:

  • Worker 2 收到了一個請求。
  • 一部分配額從全局配額轉(zhuǎn)移到 CPU 2 的每個 CPU 隊(duì)列。

Worker 1 需要精確 5 毫秒來響應(yīng)請求的機(jī)會是非常不現(xiàn)實(shí)的。如果請求需要其他一些處理時間會發(fā)生什么?

在 30 毫秒:

  • Worker 1 收到了一個請求。
  • Worker 1 只需要 1 毫秒來處理請求,而 CPU 1 的每個 CPU 存儲桶上還剩下 4 毫秒。
  • 由于每個 CPU 運(yùn)行隊(duì)列上還有剩余時間,但 CPU 1 上沒有更多可運(yùn)行線程,因此設(shè)置了一個計時器以將 slack 配額返回給全局存儲桶。這個定時器在worker 1停止運(yùn)行后設(shè)置為7ms。

在 38 毫秒:

  • CPU 1 上設(shè)置的 slack 計時器觸發(fā)并將除 1 ms 之外的所有配額返回到全局配額池。
  • 這會在 CPU 1 上留下 1 毫秒的配額。

在 41 毫秒:

  • Worker 2 收到一個長請求。
  • 所有剩余時間都從全局存儲桶轉(zhuǎn)移到 CPU 2 的 per-CPU 存儲桶,Worker 2 使用所有時間。

在 49 毫秒:

  • CPU 2 上的 Worker 2 現(xiàn)在在未完成請求的情況下受到限制。
  • 盡管 CPU 1 仍有 1ms 的配額,但仍會發(fā)生這種情況。

雖然 1 毫秒可能對雙核機(jī)器沒有太大影響,但這些毫秒在高核數(shù)機(jī)器上加起來。如果我們在 88 核 (n) 機(jī)器上遇到此行為,我們可能會在每個周期內(nèi)耗費(fèi) 87 (n-1) 毫秒。那可能無法使用的 87 毫秒或 0.87 CPU(每個Container)。這就是我們通過過度節(jié)流來達(dá)到低配額使用的方式。在最好的情況下,如果修復(fù),使受影響的應(yīng)用程序的每個實(shí)例的可用 CPU 增加 0.87,或者所需的 CPU 配額相應(yīng)減少。這些優(yōu)勢將在我們的集群中提高應(yīng)用程序密度并縮短應(yīng)用程序響應(yīng)時間。

當(dāng) 8 核和 10 核機(jī)器這個問題基本上沒有引起注意?,F(xiàn)在核心數(shù)量風(fēng)靡一時,這個問題變得更加明顯。這就是為什么我們注意到在更高核心數(shù)的機(jī)器上運(yùn)行同一應(yīng)用程序時會增加限制。

總結(jié)來說,時鐘偏差限制問題,這導(dǎo)致每個時期的配額都受到嚴(yán)格限制。這個問題一直是存在的,至少自提交 512ac999 和內(nèi)核 v4.18 以來,它就是這樣工作的。

5. linux 內(nèi)核是如何解決這個問題

當(dāng)且僅當(dāng)每個 CPU 的過期時間與全局過期時間匹配時,預(yù)補(bǔ)丁代碼才會在運(yùn)行時過期??cfs_rq->runtime_expires != cfs_b->runtime_expires??。通過檢測內(nèi)核,我證明了這種情況在我的節(jié)點(diǎn)上幾乎從未出現(xiàn)過。因此,那 1 毫秒永不過期。該補(bǔ)丁將此邏輯從基于時鐘時間更改為周期序列計數(shù),解決了內(nèi)核中長期存在的錯誤。代碼如下:

- if (cfs_rq->runtime_expires != cfs_b->runtime_expires) { 
+ if (cfs_rq->expires_seq == cfs_b->expires_seq) { 
               /* 延長本地期限,漂移以 2 個滴答為界 */ 
                cfs_rq->runtime_expires + = TICK_NSEC
       } else { 
                /* 全局截止日期提前,過期已過 */ 
                cfs_rq->runtime_remaining = 0
        }

修改問題 5.4+ 主線內(nèi)核的一部分。它們已被反向移植到許多可用的內(nèi)核中:

  1. RHEL 7: 3.10.0–1062.8.1.el7+
  2. RHEL 8: 4.18.0–147.2.1.el8_1+
  • Linux-stable: 4.14.154+, 4.19.84+, 5.3.9+
  • Ubuntu: 4.15.0–67+, 5.3.0–24+
  • Redhat Enterprise Linux:
  • CoreOS: v4.19.84+

該錯誤????https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763a9ec06c4????已被修復(fù)并合并到運(yùn)行 4.19 或更高版本的 Linux 發(fā)行版的內(nèi)核中。

但是,在閱讀kubernetes issue時????https://github.com/kubernetes/kubernetes/issues/67577????,我們可以看到各種 Linux 項(xiàng)目一直在引用這個 issue,所以我猜一些 Linux 發(fā)行版仍然存在這個 bug,并且正在努力整合修復(fù)。

如果你的 Linux 發(fā)行版的內(nèi)核版本低于 4.19,我建議你為你的節(jié)點(diǎn)升級到最新的 Linux 發(fā)行版,但無論如何,你應(yīng)該嘗試移除 CPU 限制并查看是否有任何限制.

6. 總結(jié)

監(jiān)控你的容器,是否因?yàn)?throttle 而導(dǎo)致的性能不佳,如果確實(shí)發(fā)生了,最好通過分批升級內(nèi)核版本解決,如果無法升級,可以通過方式解決:

解除限制(個人覺得這個并不是一個好主意)

  • 有性能要求的 Pod 調(diào)度到帶特定污點(diǎn)的節(jié)點(diǎn);
  • 對這些 Pod 刪除 CPU 限制,可以考慮在 namespace 級別添加限制。

增加資源

另外 CPU throttle 節(jié)流主要是因?yàn)?CPU 限制較低。它的限制影響 Cgroup 的行為。因此,一個快速解決該問題的方法是根據(jù)監(jiān)控將限值提高 10-25%,以確保降低峰值或完全避免峰值。

自動擴(kuò)容

因?yàn)閷?CPU 請求和限制設(shè)置為相同的值通常會給人們他們所期望的行為,解決此問題的簡單方法是將 CPU 請求和限制設(shè)置為相同的值并添加 HPA。讓 Pod 根據(jù)負(fù)載進(jìn)行自動擴(kuò)縮容。

責(zé)任編輯:張燕妮 來源: 云原生技術(shù)愛好者社區(qū)
相關(guān)推薦

2023-08-03 08:36:30

Service服務(wù)架構(gòu)

2022-04-22 13:32:01

K8s容器引擎架構(gòu)

2021-03-11 12:31:33

K8sCoreDNSDNS服務(wù)器

2023-11-06 07:16:22

WasmK8s模塊

2009-11-05 10:45:58

WCF服務(wù)

2022-06-01 08:00:58

KubernetesCPULinux

2023-09-06 08:12:04

k8s云原生

2023-09-08 08:09:12

k8sservice服務(wù)

2011-07-19 10:46:49

Windows 7優(yōu)化

2023-03-08 18:43:50

GPU模型隔離

2024-12-02 10:00:15

2012-12-24 09:55:15

JavaJava WebJava優(yōu)化

2020-05-12 10:20:39

K8s kubernetes中間件

2022-09-05 08:26:29

Kubernetes標(biāo)簽

2023-08-04 08:19:02

2023-05-25 21:38:30

2010-01-08 09:43:23

SQL Server分Analysis Se

2023-04-12 11:28:36

Kubernetes服務(wù)器

2023-11-07 08:23:05

2021-06-30 10:16:54

微服務(wù)架構(gòu)測試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號