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

在准入時,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 開銷,並幫助觀察使用指定開銷執行的工作負載的穩定性。

下一步

上次修改時間為 2024 年 4 月 10 日太平洋標準時間下午 5:56:解釋 Pod 開銷概念中的 RuntimeClass 名稱 (#45454) (c25ceaa535)