Pod 开销

功能状态: Kubernetes v1.24 [稳定]

在节点上运行 Pod 时,Pod 本身会占用一定量的系统资源。这些资源是除运行 Pod 中的容器所需的资源之外的额外资源。在 Kubernetes 中,Pod 开销是一种用于计算 Pod 基础架构在容器请求和限制之上消耗的资源的方法。

在 Kubernetes 中,Pod 的开销在 准入 期间根据与 Pod 的 运行时类 相关的开销进行设置。

调度 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 处理程序的工作负载将考虑内存和 CPU 开销,以便进行资源配额计算、节点调度以及 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 准入控制器完成修改后,您可以检查更新的 Pod 开销值

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

输出为

map[cpu:250m memory:120Mi]

如果定义了 资源配额,则会计算容器请求的总和以及 overhead 字段。

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

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

如果资源为每个容器定义了限制(保证型 QoS 或突发型 QoS 且定义了限制),kubelet 将为与该资源关联的 pod cgroup 设置一个上限(CPU 为 cpu.cfs_quota_us,内存为 memory.limit_in_bytes)。此上限基于容器限制的总和加上 PodSpec 中定义的 overhead

对于 CPU,如果 Pod 为保证型 QoS 或突发型 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_pod_overhead_* 指标在 kube-state-metrics 中可用,以帮助识别何时使用 Pod 开销,并帮助观察使用定义的开销运行的工作负载的稳定性。

下一步

上次修改时间为 2024 年 4 月 10 日下午 5:56 PST:解释 Pod 开销概念中的 RuntimeClass 名称(#45454)(c25ceaa535)