Pod 開銷
Kubernetes v1.24 [stable]
當你在一個節點上執行 Pod 時,Pod 本身會佔用一定量的系統資源。這些資源是 Pod 內執行容器所需資源之外的額外資源。在 Kubernetes 中,_Pod 開銷_ 是一種計算 Pod 基礎設施在容器請求和限制之外所消耗資源的方式。
在 Kubernetes 中,Pod 的開銷是根據與 Pod 的 RuntimeClass 相關的開銷在 准入 時設定的。
在排程 Pod 時,Pod 的開銷會額外計入容器資源請求的總和。類似地,kubelet 在確定 Pod cgroup 大小以及執行 Pod 驅逐排名時,也會將 Pod 開銷計算在內。
配置 Pod 開銷
你需要確保使用的是定義了 overhead
欄位的 RuntimeClass
。
使用示例
要使用 Pod 開銷,你需要一個定義了 overhead
欄位的 RuntimeClass。例如,你可以使用以下 RuntimeClass 定義,它與虛擬化容器執行時(在本例中為 Kata Containers 結合 Firecracker 虛擬機器監視器)配合使用,該執行時每個 Pod 大約使用 120MiB 用於虛擬機器和客戶作業系統。
# You need to change this example to match the actual runtime name, and per-Pod
# resource overhead, that the container runtime is adding in your cluster.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-fc
handler: kata-fc
overhead:
podFixed:
memory: "120Mi"
cpu: "250m"
指定 kata-fc
RuntimeClass 處理器建立的工作負載將在資源配額計算、節點排程以及 Pod cgroup 大小調整中考慮記憶體和 CPU 開銷。
考慮執行給定的示例工作負載 test-pod
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
runtimeClassName: kata-fc
containers:
- name: busybox-ctr
image: busybox:1.28
stdin: true
tty: true
resources:
limits:
cpu: 500m
memory: 100Mi
- name: nginx-ctr
image: nginx
resources:
limits:
cpu: 1500m
memory: 100Mi
注意
如果 Pod 定義中只指定了limits
,kubelet 會從這些限制中推斷出 requests
,並將其設定為與定義的 limits
相同。在准入時,RuntimeClass 准入控制器 會更新工作負載的 PodSpec,以包含 RuntimeClass 中描述的 overhead
。如果 PodSpec 已定義此欄位,則 Pod 將被拒絕。在給定的示例中,由於只指定了 RuntimeClass 名稱,准入控制器會修改 Pod 以包含一個 overhead
。
在 RuntimeClass 准入控制器進行修改後,你可以檢查更新後的 Pod 開銷值
kubectl get pod test-pod -o jsonpath='{.spec.overhead}'
輸出為:
map[cpu:250m memory:120Mi]
如果定義了 ResourceQuota,則容器請求的總和以及 overhead
欄位都會被計算在內。
當 kube-scheduler 決定哪個節點應該執行新的 Pod 時,排程器會考慮該 Pod 的 overhead
以及該 Pod 的容器請求總和。對於本例,排程器將請求和開銷相加,然後尋找一個具有 2.25 CPU 和 320 MiB 可用記憶體的節點。
一旦 Pod 被排程到節點,該節點上的 kubelet 就會為 Pod 建立一個新的 cgroup。在 Pod cgroup 中,底層容器執行時將建立容器。
如果資源為每個容器定義了限制(Guaranteed QoS 或定義了限制的 Burstable QoS),kubelet 將為與該資源關聯的 Pod cgroup 設定上限(CPU 的 cpu.cfs_quota_us 和記憶體的 memory.limit_in_bytes)。此上限基於容器限制的總和加上 PodSpec 中定義的 overhead
。
對於 CPU,如果 Pod 是 Guaranteed 或 Burstable QoS,kubelet 將根據容器請求的總和加上 PodSpec 中定義的 overhead
來設定 cpu.shares
。
檢視我們的示例,驗證工作負載的容器請求
kubectl get pod test-pod -o jsonpath='{.spec.containers[*].resources.limits}'
容器請求總量為 2000m CPU 和 200MiB 記憶體
map[cpu: 500m memory:100Mi] map[cpu:1500m memory:100Mi]
對照節點觀察到的結果進行檢查
kubectl describe node | grep test-pod -B2
輸出顯示請求為 2250m CPU 和 320MiB 記憶體。這些請求包含了 Pod 開銷
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default test-pod 2250m (56%) 2250m (56%) 320Mi (1%) 320Mi (1%) 36m
驗證 Pod cgroup 限制
檢查工作負載執行節點上的 Pod 記憶體 cgroup。在以下示例中,在節點上使用了 crictl
,它提供了一個 CRI 相容容器執行時的 CLI。這是一個高階示例,旨在展示 Pod 開銷行為,不期望使用者直接在節點上檢查 cgroup。
首先,在特定節點上,確定 Pod 識別符號
# Run this on the node where the Pod is scheduled
POD_ID="$(sudo crictl pods --name test-pod -q)"
由此,你可以確定 Pod 的 cgroup 路徑
# Run this on the node where the Pod is scheduled
sudo crictl inspectp -o=json $POD_ID | grep cgroupsPath
生成的 cgroup 路徑包含 Pod 的 pause
容器。Pod 級別 cgroup 在上一級目錄。
"cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"
在這種特定情況下,Pod cgroup 路徑是 kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2
。驗證 Pod 級別 cgroup 的記憶體設定
# Run this on the node where the Pod is scheduled.
# Also, change the name of the cgroup to match the cgroup allocated for your pod.
cat /sys/fs/cgroup/memory/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/memory.limit_in_bytes
這是 320 MiB,符合預期
335544320
可觀察性
kube-state-metrics 中提供了一些 kube_pod_overhead_*
指標,以幫助識別何時使用了 Pod 開銷,並幫助觀察使用指定開銷執行的工作負載的穩定性。
下一步
- 瞭解有關 RuntimeClass 的更多資訊
- 閱讀 PodOverhead 設計 增強提案以獲取更多上下文