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