TT Lab
开始
学习 学习路径 课程

KCNA — Kubernetes 与云原生入门

低使用率不等于可用调度预算

在 TT Lab 中继续学习

一句话总结

requests 是用来挑选位置的承诺,limits 是限制运行中可使用量的设置。不能仅凭 CPU 使用率低,就判断有新 Pod 可以进入的位置。

为什么需要它

教室里只坐着五个人,新学员却进不去。座位看起来是空的,但其余椅子已经为下午的课预留好了。现在坐着的人数和已预留的座位,是两本不同的账簿。在 Kubernetes 中也是如此,当前使用量和用于调度的资源请求量并不相同。预留的比喻是为了帮助理解放置判断,并不表示把某一个 CPU 核心在物理上专门分配给某个容器。

假设团队部署了一个小型 Python 应用,而 Pod 一直停在 Pending。代码只是在休眠,几乎不使用 CPU。但清单里误把 requests.cpu 写成了 8,而所有节点都比它小。应用有多清闲,解决不了这个问题。因为在应用启动之前,声明的请求就已经超过了可放置节点的大小。

工作原理

首先区分四个数字。

数字 回答什么问题 查看的位置
capacity 节点报告的资源总量是多少 Node.status.capacity
allocatable 可用于放置 Pod 的资源量是多少 Node.status.allocatable
requests 放置这个 Pod 时要计算的请求量是多少 容器 resources.requests
实际使用量 在特定观测区间内用了多少 资源指标 API、监控

本课时专注于普通容器的 CPU 和内存请求。如果有 init 容器、Pod 开销、Pod 级别的资源设置、扩展资源等,还需要另外确认计算规则。不要把单个容器的简单算术原样套用到所有工作负载上。

例如,某节点的 allocatable CPU 为 2,已放置的请求合计为 1.4,那么加上新的 800m 请求后合计为 2.2。仅 CPU 这一项就已经不满足。即使观测到实际使用量为 200m,请求合计也不会自己减少。反过来,请求合计满足,也不保证放置成功。内存、节点选择条件、taint、卷等其他条件也必须满足。

CPU 1 是一个 CPU 单位,等于 1000m。250m 是 0.25 CPU,而不是整个节点的 250%。内存的 Mi 和 M 也不相同。64Mi 是 64×1024×1024 字节,而 64M 是 64×1000×1000 字节。阅读资源问题时如果省略单位,就会把不同的账簿拿同一个数字去比较。

limits 是另一条轴。CPU 限制表现为限制运行时间的 throttling,内存限制则视情况表现为 OOM 终止。超过 requests 并不会马上被终止。请求量写得低、限制量写得高,在有余量时可以多用一些。不过,无条件压低请求并不是办法。请求过低,会把过多的任务派到同一个节点上,造成性能竞争和压力。

在现场相遇的样子

练习缩小失败位置的顺序。

kubectl -n kcna-capacity get pod oversized -o json
kubectl -n kcna-capacity describe pod oversized
kubectl get nodes -o json

第一,查看 Pod 对象是否真的存在。第二,查看是否有 spec.nodeName,以及 PodScheduled 条件。第三,读取对应该 Pod UID 的 FailedScheduling 事件。如果拿了同名的过去 Pod 的事件,就可能把替换之前的错误误认为当前的原因。Pending 也包含镜像下载等其他准备过程,所以不能仅凭这一个词就断定是 CPU 不足。

如果在这里确认了 Insufficient cpu,就把声明的请求与节点的 allocatable 及已有请求进行对照。如果请求确实需要这么大,就考虑更大的节点、拆分任务、清理不必要的预留等选项。如果是笔误,就要有依据地修改。删除生产中其他团队的 Pod,或者通过修改节点状态来凑数字,都不是诊断。

后续实验要做什么

声明一个比个人 k3s 的实际 allocatable 更大的 CPU 请求,但不运行消耗 CPU 的负载程序。收集保存在 API 中的 Pod 无法放置的证据,然后只回收对应该 UID 的测试 Pod,并比较 50m 请求的小 Pod 能否启动。另一个命名空间中的正常对比组要保留到最后。这个实验不同于直接测量 CPU 饱和、throttling 和 OOM 的实验。

官方依据