Kubernetes No CPU Limit:不限制 CPU 可能會(huì)更好
介紹
Kubernetes 是一個(gè)開(kāi)源容器編排平臺(tái),可幫助編排您的容器化應(yīng)用程序。使用Kubernetes之后 ,無(wú)需擔(dān)心應(yīng)用程序的擴(kuò)展和可用性。在將應(yīng)用程序遷移到Kubernetes 集群之前,集群需要擁有災(zāi)難恢復(fù)的高可用性,以及安全、可擴(kuò)展和優(yōu)化的特性。
Kubernetes 利用來(lái)自底層虛擬機(jī)或物理機(jī)的資源,然后由各個(gè)容器使用。最常見(jiàn)的資源是 CPU 和 RAM,還有其他資源。如果需要,Kubernetes 可以限制這些資源及其容器對(duì)它們的消耗。對(duì)容器的 CPU/Memory 使用設(shè)置限制是一種普遍的做法。
CPU/Memory 限制是容器可以使用的最大 CPU/Memory。它限制容器使用節(jié)點(diǎn)上所有可用的 CPU/Memory。因此,從理論上講,這聽(tīng)起來(lái)不錯(cuò),可以保護(hù)節(jié)點(diǎn)不會(huì)耗盡資源并變得無(wú)響應(yīng)。
CPU 和內(nèi)存限制的實(shí)現(xiàn)方式和工作方式彼此不同。內(nèi)存限制更容易檢測(cè)到,我們只需要檢查 pod 的上次重啟狀態(tài),如果它由于內(nèi)存不足(OOMKilled)而被殺死。另一方面,為了實(shí)現(xiàn) CPU 限制,Kubernetes 使用內(nèi)核限制并暴露指標(biāo)而不是使用 cgroup 相關(guān)的指標(biāo),這使得很難檢測(cè) CPU 限制。這意味著,如果應(yīng)用程序超出 CPU 限制,它就會(huì)受到限制。
這就是問(wèn)題所在。
在我們了解 CPU throttling之前,讓我們了解 CPU 限制的需求以及它是如何工作的。
如果我們沒(méi)有在 Kubernetes 中指定 CPU limit 與 request怎么辦?
如果您不指定 CPU 限制,則容器將沒(méi)有任何 CPU 上限,然后它可以使用節(jié)點(diǎn)上所有可用的 CPU。這會(huì)使 CPU 密集型容器降低同一節(jié)點(diǎn)上的其他容器的速度,并可能耗盡節(jié)點(diǎn)上所有可用的 CPU。這反過(guò)來(lái)又會(huì)觸發(fā)諸如 kubelet 等 Kubernetes 組件變得無(wú)響應(yīng)的事件。這可以使節(jié)點(diǎn)變?yōu)?NotReady 狀態(tài),并且來(lái)自該節(jié)點(diǎn)的容器將被重新調(diào)度到某個(gè)其他節(jié)點(diǎn)上。
什么是 CPU 限制以及 CPU 限制如何工作?
CPU throttling確保如果應(yīng)用程序超過(guò)指定的限制,它就會(huì)受到限制。有時(shí),即使 CPU 使用率接近限制,也可以觀(guān)察到容器throttling。發(fā)生這種情況是因?yàn)?Linux 內(nèi)核中的一個(gè)錯(cuò)誤會(huì)不必要地限制擁有 CPU 限制的容器。
現(xiàn)在,在我們繼續(xù)之前,讓我們首先了解 CPU 限制在 Kubernetes 中是如何工作的。Kubernetes使用CFS (https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/) 配額來(lái)對(duì)運(yùn)行應(yīng)用程序的 pod 實(shí)施 CPU 限制。Completely Fair Scheduler (CFS) 是一個(gè)進(jìn)程調(diào)度程序,它根據(jù)時(shí)間段而不是基于可用的 CPU 功率來(lái)處理執(zhí)行進(jìn)程的 CPU 資源分配,并使用兩個(gè)files:cfs_period_us 和 cfs_quota_us。(https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt)
- cpu.cfs_quota_us:一段時(shí)間內(nèi)的總可用運(yùn)行時(shí)間[以微秒為單位]
- cpu.cfs_period_us:一個(gè)周期的長(zhǎng)度[以微秒為單位]
cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
o/p → 100000
這里,100000 us = 100 ms
cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
o/p → -1
這里,cpu.cfs_quota_us 的值為 -1 表示沒(méi)有任何帶寬限制。
例如,有一個(gè)單線(xiàn)程應(yīng)用程序在 CPU 上運(yùn)行,但有 CPU 限制,應(yīng)用程序需要 200 毫秒的處理時(shí)間。應(yīng)用程序完成其請(qǐng)求的圖表如下所示。
在第二種情況下,如果我們?yōu)閼?yīng)用程序設(shè)置 0.4 個(gè) CPU 的 CPU 限制,則應(yīng)用程序在每 100 毫秒周期后獲得 40
毫秒的運(yùn)行時(shí)間。在這里,之前需要 200 毫秒的請(qǐng)求現(xiàn)在需要 440 毫秒才能完成。
從上面的例子可以看出,CPU 限制是問(wèn)題的真正原因。
案例
讓我們以以下示例為例,其中工作節(jié)點(diǎn)有1 個(gè) CPU。您可以在 linux 服務(wù)器上使用“cat /proc/cpuinfo”命令檢查它。
現(xiàn)在,在我們創(chuàng)建有 CPU 限制的 Pod 之前,讓我們?cè)诩荷喜渴鹨粋€(gè)“Metrics
Server”,它可以用來(lái)獲取資源使用率的相關(guān)指標(biāo)。尤其是Pod/Node的指標(biāo)。
可以使用以下命令部署 Metrics 服務(wù)器,這些命令首先克隆“kubernetes-metrics-server”git
存儲(chǔ)庫(kù)并在集群上創(chuàng)建所需的對(duì)象。
git clone https://github.com/kodekloudhub/kubernetes-metrics-server.git
cd kubernetes-metrics-server/
kubectl apply -f .
要?jiǎng)?chuàng)建有 CPU 請(qǐng)求和限制的 pod,請(qǐng)使用以下 pod 定義創(chuàng)建一個(gè)文件“pod-with-cpu-limit.yaml”。這為 Pod 設(shè)置了Limit “1”和Request “0.5”。Request是容器預(yù)留的資源,Limit確保容器永遠(yuǎn)不會(huì)超過(guò)某個(gè)值。 (https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-resource-requests-and-limits)
requests:
cpu: 100m
limits:
cpu: 500m
這將創(chuàng)建一個(gè)沒(méi)有任何問(wèn)題的 pod,因?yàn)?Limit 不超過(guò)我們?cè)诠ぷ鞴?jié)點(diǎn)上擁有的實(shí)際 CPU 數(shù)量,并且請(qǐng)求在我們指定的限制范圍內(nèi)。
使用以下命令創(chuàng)建一個(gè) pod:
kubectl apply -f pod-with-cpu-limit.yaml
kubectl get pods
kubectl describe pod cpu-demo-pod
現(xiàn)在,如果您使用以下命令檢查 pod 的實(shí)際 CPU 使用率,它是 1003m(1 個(gè) CPU)。由于我們傳遞給 pod 的參數(shù)超過(guò)了我們?cè)谙拗浦兄付ǖ膮?shù),這里 CPU 正在throttling。
使用以下命令檢查使用情況。
kubectl top pods cpu-demo-pod
但是,如果您指定的 CPU 限制超過(guò)了工作節(jié)點(diǎn)上可用的數(shù)量,您將面臨問(wèn)題并且 Pod 將進(jìn)入 Pending 狀態(tài)。
首先刪除現(xiàn)有的 pod,更改 CPU 限制和請(qǐng)求,然后嘗試使用以下命令創(chuàng)建一個(gè) Pod。
kubectl get pods
kubectl delete pod cpu-demo-pod
kubectl apply -f pod-with-cpu-limit.yaml
通過(guò)描述 Pod 來(lái)檢查失敗的原因。
kubectl get pods
kubectl describe pod cpu-demo-pod
您可以清楚地看到,由于 CPU 請(qǐng)求超過(guò)了工作節(jié)點(diǎn)上實(shí)際可用的 CPU,因此 Pod 無(wú)法創(chuàng)建并處于 Pending 狀態(tài)。
刪除 CPU 限制時(shí)要小心
就集群穩(wěn)定性而言,移除 CPU 限制并不是一個(gè)容易的決定。如果默認(rèn)情況下未設(shè)置 CPU 限制,則它的默認(rèn)限制則是節(jié)點(diǎn)的最高可用值。
在取消 CPU 限制之前,了解應(yīng)用如何工作以及它們對(duì) CPU 的需求非常重要。
我們可以嘗試移除對(duì)延遲敏感的應(yīng)用的 CPU 限制,而不是隨意的從所有應(yīng)用中移除 CPU 限制。
隔離沒(méi)有 CPU 限制的應(yīng)用是個(gè)好的方式。如果資源分配出現(xiàn)任何問(wèn)題,這將有助于輕松控制和識(shí)別此類(lèi)應(yīng)用pod。
結(jié)論
如果 Docker container/Kubernetes Pod 在 Linux 系統(tǒng)上運(yùn)行,那么它們可能會(huì)由于throttling而表現(xiàn)異常。雖然這可能很危險(xiǎn),但刪除 CPU Limited 是解決此限制問(wèn)題的解決方案。這也可以通過(guò)將內(nèi)核升級(jí)到修復(fù) CPU throttling問(wèn)題的版本來(lái)解決。沒(méi)有 CPU 限制的應(yīng)用程序也可以隔離到不同的節(jié)點(diǎn),以便更容易找出影響pod容器性能的罪魁禍?zhǔn)住?/p>