Pod 开销
FEATURE STATE: Kubernetes v1.18
beta
该功能目前处于 beta 状态,意味着:
- 版本名称包含 beta (例如 v2beta3)。
- 代码经过了充分测试,启用该功能被认为是安全的。默认情况下被启用。
- 对整体功能的支持在未来不会被移除,尽管细节上可能会做更改。
- 在后续的 beta 或稳定版本中,对象的模式、语义可能以不兼容的方式发生变化。当这种情况发生时,我们将提供迁移到下一个版本的说明。这可能需要删除、编辑和重建 API 对象,编辑过程可能需要一些思考。这可能导致依赖该功能的应用程序停机一段时间。
- 建议仅在非业务关键场景使用该功能,因为在后续版本中可能会发生不兼容的更改。如果您有多个可以独立升级的集群,那么您可能可以放松这个限制。
- 请尝试使用我们的 beta 版功能,并给出反馈!在它们退出 beta 测试阶段之后,我们将很难去做更多的更改。
在节点上运行 Pod 时,Pod 本身占用大量系统资源。这些资源是运行 Pod 内容器所需资源的附加资源。 POD 开销 是一个特性,用于计算 Pod 基础设施在容器请求和限制之上消耗的资源。
Pod 开销
在 Kubernetes 中,Pod 的开销是根据与 Pod 的 RuntimeClass 相关联的开销在 准入 时设置的。
当启用 Pod 开销时,在调度 Pod 时,除了考虑容器资源请求的总和外,还要考虑 Pod 开销。类似地,Kubelet 将在确定 Pod cgroup 的大小和执行 Pod 驱逐排序时包含 Pod 开销。
启用 Pod 开销
您需要确保在集群中启用了 PodOverhead
特性门(在 1.18 默认是开启的),以及一个用于定义 overhead
字段的 RuntimeClass
。
使用示例
要使用 PodOverhead 特性,需要一个定义 overhead
字段的 RuntimeClass. 作为例子,可以在虚拟机和来宾操作系统中通过一个虚拟化容器运行时来定义 RuntimeClass 如下,其中每个 Pod 大约使用 120MiB:
---
kind: RuntimeClass
apiVersion: node.k8s.io/v1beta1
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
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 决定在哪一个节点调度运行新的 Pod 时,调度器会兼顾该 Pod 的 overhead
以及该 Pod 的容器请求总量。在这个示例中,调度器将资源请求和开销相加,然后寻找具备 2.25 CPU 和 320 MiB 内存可用的节点。
一旦 Pod 调度到了某个节点, 该节点上的 kubelet 将为该 Pod 新建一个 cgroup一组具有可选资源隔离、审计和限制的 Linux 进程。 . 底层容器运行时将在这个 pod 中创建容器。
如果该资源对每一个容器都定义了一个限制(定义了受限的 Guaranteed QoS 或者 Bustrable 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]
对照从节点观察到的情况来检查一下:
kubectl describe node | grep test-pod -B2
该输出显示请求了 2250m CPU 以及 320MiB 内存,包含了 PodOverhead 在内:
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 的内存 cgroups. 在接下来的例子中,将在该节点上使用具备 CRI 兼容的容器运行时命令行工具 crictl
. 这是一个展示 PodOverhead 行为的进阶示例,用户并不需要直接在该节点上检查 cgroups.
首先在特定的节点上确定该 Pod 的标识符:ying
# 在该 Pod 调度的节点上执行如下命令:
POD_ID="$(sudo crictl pods --name test-pod -q)"
可以依此判断该 Pod 的 cgroup 路径:
# 在该 Pod 调度的节点上执行如下命令:
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 设置:
# 在该 Pod 调度的节点上执行这个命令。
# 另外,修改 cgroup 的名称以匹配为该 pod 分配的 cgroup。
cat /sys/fs/cgroup/memory/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/memory.limit_in_bytes
和预期的一样是 320 MiB
335544320
可观察性
在 kube-state-metrics 中可以通过 kube_pod_overhead
指标来协助确定何时使用 PodOverhead 以及协助观察以一个既定开销运行的工作负载的稳定性。 该特性在 kube-state-metrics 的 1.9 发行版本中不可用,不过预计将在后续版本中发布。在此之前,用户需要从源代码构建 kube-state-metrics.