iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Kubernetes

Think Again Kubernetes系列 第 29

我要獨佔 CPU:CPU Manager

  • 分享至 

  • xImage
  •  

前面提到設定 resources.limits.cpu 會造成 CPU throttling,造成資源沒有效率的應用,也影響到應用程式的表現,Kubernetes 發現了這個問題,所以提出了一個解決方案:CPU Manager

CPU Manager 的目的是用 cpuset Pod 可以獨佔 CPU,而使用條件有三個

  1. kubelet 設定中 cpu_manager_policy 需為 static

  2. QoS Class = guaranteed

  3. limits.cpu 單位需為整數

剛 cpu_manager_policy 設定為 static 之後,CPU Manager 會維護一個 CPU Pool,讓 KubeReservedSystemReservedburstableQoS以及 besteffortQos 共同用這個 CPU Pool,而當有 Guaranteed Pod 且 limits.cpu 單位是整數的時候,就會把 cpuset 設定在上面。

測試環境:

作者建置了一個 GKE,並把其中一個 node pool 的 kubelet 設定 cpu_manager_policy=static,

測試計劃

佈署一個 Nginx Deployment,然後 resources.limits 以及 resources.requests 都設定為 1

這樣的設定就滿足了 cpu_manager_policy=static、QoS Class = guaranteed 以及 limits.cpu 單位是整數的條件,所以可以被獨佔。

測試結果

我們可以看到 kubelet 的日誌顯示 Pod 被綁定在哪一個 CPU 上面

Oct 08 14:16:03 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:03.681601    1704 state_mem.go:80] "Updated desired CPUSet" podUID="e93e3ec0-4d04-4795-85ff-6a2c58eaef0e" containerName="fluentbit" cpuSet="0"
Oct 08 14:16:03 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:03.775045    1704 state_mem.go:80] "Updated desired CPUSet" podUID="e93e3ec0-4d04-4795-85ff-6a2c58eaef0e" containerName="fluentbit-gke" cpuSet="0"
Oct 08 14:16:03 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:03.929579    1704 state_mem.go:80] "Updated desired CPUSet" podUID="e93e3ec0-4d04-4795-85ff-6a2c58eaef0e" containerName="fluentbit-metrics-collector" cpuSet="0"
Oct 08 14:16:03 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:03.982960    1704 state_mem.go:80] "Updated desired CPUSet" podUID="94ff5e11-f73c-452d-9179-a91b189e199a" containerName="gke-metrics-agent" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.019762    1704 state_mem.go:80] "Updated desired CPUSet" podUID="94ff5e11-f73c-452d-9179-a91b189e199a" containerName="core-metrics-exporter" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.054535    1704 state_mem.go:80] "Updated desired CPUSet" podUID="94ff5e11-f73c-452d-9179-a91b189e199a" containerName="prometheus-metrics-collector" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.103424    1704 state_mem.go:80] "Updated desired CPUSet" podUID="96a35632-109d-4773-b4ea-1253befc0e36" containerName="csi-driver-registrar" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.153779    1704 state_mem.go:80] "Updated desired CPUSet" podUID="96a35632-109d-4773-b4ea-1253befc0e36" containerName="gce-pd-driver" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.196431    1704 state_mem.go:80] "Updated desired CPUSet" podUID="f5376619-c45d-4f36-9a5e-11e8ac5254d1" containerName="konnectivity-agent" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.232609    1704 state_mem.go:80] "Updated desired CPUSet" podUID="f5376619-c45d-4f36-9a5e-11e8ac5254d1" containerName="konnectivity-agent-metrics-collector" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.285655    1704 state_mem.go:80] "Updated desired CPUSet" podUID="eeec0d059b9283abacfbba2e302d3e00" containerName="kube-proxy" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.331036    1704 state_mem.go:80] "Updated desired CPUSet" podUID="5f7caf44-29f3-4ffc-92f1-fa9cdd409be7" containerName="prometheus" cpuSet="0"
Oct 08 14:16:04 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:04.386277    1704 state_mem.go:80] "Updated desired CPUSet" podUID="5f7caf44-29f3-4ffc-92f1-fa9cdd409be7" containerName="config-reloader" cpuSet="0"
Oct 08 14:16:07 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:07.604113    1704 state_mem.go:80] "Updated desired CPUSet" podUID="17838689-d6c7-4dd0-a084-cba58fdc9759" containerName="nginx" cpuSet="1"

我們可以很明顯的觀察到,除了 nginx 之外都被分配到 cpuSet=0

Oct 08 14:16:07 gke-my-gke-cluster-static-cpu-node-po-3a6376be-d941 kubelet[1704]: I1008 14:16:07.604113    1704 state_mem.go:80] "Updated desired CPUSet" podUID="17838689-d6c7-4dd0-a084-cba58fdc9759" containerName="nginx" cpuSet="1"

而日誌顯示 nginx 被綁定到 cpu 1

接下來我們從 cgroup 可以看到 cpuset 被綁定到 cpu 1

cat /sys/fs/cgroup/kubepods.slice/kubepods-pod17838689_d6c7_4dd0_a084_cba58fdc9759.slice/cri-containerd-e69cb15c5c8c402574f0b96d866ee53ffe36175ca18f4a476f6d7b8453be7c63.scope/cpuset.cpus
1

其他設定

為了避免 noisy neighbours problem,CPU Manager 可以設定讓 Pod 獨佔物理 CPU 而不是 vCPU,這個功能從 full-pcpus-only 可以開啟。
除此之外還有 NUMA 相關的設定,不過作者目前還沒有機會碰到,所以就不多做介紹了。

REF:

https://www.hwchiu.com/docs/2023/container-vm#monitor

目前我看到寫 cgroup 最詳細的文章,裡面關於 CPU Throttling 的圖解相當清楚。

https://medium.com/geekculture/layer-by-layer-cgroup-in-kubernetes-c4e26bda676c
關於 Layered cgroup 的介紹

https://github.com/kubernetes/design-proposals-archive/blob/main/node/node-allocatable.md

關於 Layered cgroup 的 KEP

https://www.youtube.com/watch?v=x9_9iaVszpM&themeRefresh=1

從對於 resources.limits 以及 resources.requests 的誤解這樣的方式敘事,是看到這個影片的靈感

https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/

Static CPU 的文件


上一篇
利用 kind 探索 Layered cgroup
下一篇
Day 30 ArgoCD: 架構、CI/CD以及 GitOps Bridge
系列文
Think Again Kubernetes31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言