Pod 开销

特性状态: Kubernetes v1.24 [稳定]

当你在 Node 上运行 Pod 时,Pod 本身会占用一定量的系统资源。这些资源是运行 Pod 内部容器所需的资源之外的额外资源。在 Kubernetes 中,Pod Overhead 是一种计算 Pod 基础设施消耗的资源的方式,这些资源是在容器请求和限制之上计算的。

在 Kubernetes 中,Pod 的 overhead 在 准入 (admission) 时根据与 Pod 的 RuntimeClass 相关的 overhead 进行设置。

在调度 Pod 时,除了容器资源请求的总和之外,还会考虑 Pod 的 overhead。 同样,kubelet 在调整 Pod cgroup 大小时,以及在执行 Pod 驱逐排序时,将包含 Pod 的 overhead。

配置 Pod overhead

你需要确保使用定义了 overhead 字段的 RuntimeClass

使用示例

要使用 Pod overhead,你需要一个定义了 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 overhead。

考虑运行给定的示例工作负载 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 准入控制器 (admission controller) 会更新工作负载的 PodSpec,以包含 RuntimeClass 中描述的 overhead。 如果 PodSpec 已经定义了此字段,则 Pod 将被拒绝。 在给定的示例中,由于仅指定了 RuntimeClass 名称,因此准入控制器会修改 Pod 以包含 overhead

在 RuntimeClass 准入控制器进行修改后,你可以检查更新的 Pod overhead 值

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

输出如下:

map[cpu:250m memory:120Mi]

如果定义了 ResourceQuota,则容器请求的总和以及 overhead 字段将被计算在内。

当 kube-scheduler 决定哪个节点应该运行新的 Pod 时,调度器会考虑该 Pod 的 overhead 以及该 Pod 的容器请求总和。 对于此示例,调度器会添加请求和 overhead,然后查找具有 2.25 CPU 和 320 MiB 内存的节点。

一旦 Pod 被调度到节点,该节点上的 kubelet 会为该 Pod 创建一个新的 cgroup。 底层容器运行时将在该 cgroup 中创建容器。

如果资源为每个容器定义了限制(Guaranteed QoS 或 Burstable QoS,并定义了限制),kubelet 将基于容器限制的总和加上 PodSpec 中定义的 overhead 为 pod cgroup 设置该资源的上限(cpu.cfs_quota_us 用于 CPU 和 memory.limit_in_bytes 内存)。

对于 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 overhead

  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 overhead 行为,并且预计用户不需要直接在节点上检查 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 overhead 以及帮助观察具有定义 overhead 的工作负载的稳定性。

接下来

最后修改时间:2024 年 4 月 10 日下午 5:56 PST:解释 Pod Overhead 概念中的 RuntimeClass 名称 (#45454) (c25ceaa535)