Kubernetes Pod開銷

2022-05-26 10:02 更新

Pod 開銷

FEATURE STATE: Kubernetes v1.24 [stable]

在節(jié)點上運行 Pod 時,Pod 本身占用大量系統(tǒng)資源。這些是運行 Pod 內容器所需資源之外的資源。 在 Kubernetes 中,POD 開銷 是一種方法,用于計算 Pod 基礎設施在容器請求和限制之上消耗的資源。

在 Kubernetes 中,Pod 的開銷是根據(jù)與 Pod 的 RuntimeClass 相關聯(lián)的開銷在準入時設置的。

如果啟用了 Pod Overhead,在調度 Pod 時,除了考慮容器資源請求的總和外,還要考慮 Pod 開銷。 類似地,kubelet 將在確定 Pod cgroups 的大小和執(zhí)行 Pod 驅逐排序時也會考慮 Pod 開銷。

配置 Pod 開銷 

你需要確保使用一個定義了 ?overhead ?字段的 ?RuntimeClass?。

使用示例

要使用 Pod 開銷,你需要一個定義了 ?overhead ?字段的 RuntimeClass。 作為例子,下面的 RuntimeClass 定義中包含一個虛擬化所用的容器運行時, RuntimeClass 如下,其中每個 Pod 大約使用 120MiB 用來運行虛擬機和寄宿操作系統(tǒng):

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata-fc
handler: kata-fc
overhead:
  podFixed:
    memory: "120Mi"
    cpu: "250m"

通過指定 ?kata-fc? RuntimeClass 處理程序創(chuàng)建的工作負載會將內存和 CPU 開銷計入資源配額計算、節(jié)點調度以及 Pod cgroup 尺寸確定。

假設我們運行下面給出的工作負載示例 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 準入控制器進行修改后,你可以查看更新后的 PodSpec:

kubectl get pod test-pod -o jsonpath='{.spec.overhead}'

輸出:

map[cpu:250m memory:120Mi]

如果定義了 ResourceQuata, 則容器請求的總量以及 ?overhead ?字段都將計算在內。

當 kube-scheduler 決定在哪一個節(jié)點調度運行新的 Pod 時,調度器會兼顧該 Pod 的 ?overhead ?以及該 Pod 的容器請求總量。在這個示例中,調度器將資源請求和開銷相加, 然后尋找具備 2.25 CPU 和 320 MiB 內存可用的節(jié)點。

一旦 Pod 被調度到了某個節(jié)點, 該節(jié)點上的 kubelet 將為該 Pod 新建一個 cgroup。 底層容器運行時將在這個 Pod 中創(chuàng)建容器。

如果該資源對每一個容器都定義了一個限制(定義了限制值的 Guaranteed QoS 或者 Burstable QoS),kubelet 會為與該資源(CPU 的 ?cpu.cfs_quota_us? 以及內存的 ?memory.limit_in_bytes?) 相關的 Pod cgroup 設定一個上限。該上限基于 PodSpec 中定義的容器限制總量與 ?overhead ?之和。

對于 CPU,如果 Pod 的 QoS 是 Guaranteed 或者 Burstable,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]

對照從節(jié)點觀察到的情況來檢查一下:

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 限制

在工作負載所運行的節(jié)點上檢查 Pod 的內存 cgroups。在接下來的例子中, 將在該節(jié)點上使用具備 CRI 兼容的容器運行時命令行工具 ?crictl?。 這是一個顯示 Pod 開銷行為的高級示例, 預計用戶不需要直接在節(jié)點上檢查 cgroups。 首先在特定的節(jié)點上確定該 Pod 的標識符:

# 在該 Pod 被調度到的節(jié)點上執(zhí)行如下命令:
POD_ID="$(sudo crictl pods --name test-pod -q)"

可以依此判斷該 Pod 的 cgroup 路徑:

# 在該 Pod 被調度到的節(jié)點上執(zhí)行如下命令:
sudo crictl inspectp -o=json $POD_ID | grep cgroupsPath

執(zhí)行結果的 cgroup 路徑中包含了該 Pod 的 ?pause ?容器。Pod 級別的 cgroup 在即上一層目錄。

  "cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"

在這個例子中,該 Pod 的 cgroup 路徑是 ?kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2?。 驗證內存的 Pod 級別 cgroup 設置:

# 在該 Pod 被調度到的節(jié)點上執(zhí)行這個命令。
# 另外,修改 cgroup 的名稱以匹配為該 Pod 分配的 cgroup。
 cat /sys/fs/cgroup/memory/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/memory.limit_in_bytes

和預期的一樣,這一數(shù)值為 320 MiB。

335544320

可觀察性 

在 kube-state-metrics 中可以通過 ?kube_pod_overhead_*? 指標來協(xié)助確定何時使用 Pod 開銷, 以及協(xié)助觀察以一個既定開銷運行的工作負載的穩(wěn)定性。 該特性在 kube-state-metrics 的 1.9 發(fā)行版本中不可用,不過預計將在后續(xù)版本中發(fā)布。 在此之前,用戶需要從源代碼構建 kube-state-metrics。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號