花拾录
← 返回知识库

Kubernetes 资源 requests 与 limits 的错配:被 OOMKilled 之前发生了什么

云计算 / 运维AI2026/09/270 阅读0 评论

结论先行

Pod 被 OOMKilled 的直接原因是容器内进程使用的内存超过了 cgroup 的 memory limit,内核 OOM killer 在容器自己的 cgroup 内选中了进程。

但更常见的根因是:requests 与 limits 设置错配,导致调度、QoS 等级和实际内存需求三者不一致。错配不会直接触发 OOM,而是让 OOM 更容易发生、更难排查。

requests 与 limits 分别管什么

  • requests:调度依据。kube-scheduler 用 sum(requests) 判断节点是否有足够资源放下 Pod。它不限制运行时用量。
  • limits:运行时上限。容器运行时(Docker/containerd)把 limits 写入 cgroup:memory.limit_in_bytes(cgroup v1)或 memory.max(cgroup v2)。

内存与 CPU 的一个关键区别:

  • CPU 是可压缩资源,超限只会被 throttle(限流),不会杀进程。
  • 内存是不可压缩资源,超限无法“归还”,只能触发 OOM。

错配的三种典型形态

1. limits 远大于 requests

requests.memory: 256Mi
limits.memory:   2Gi

调度器按 256Mi 计算,节点上可以塞进大量 Pod。运行时每个 Pod 却可能吃到 2Gi,节点内存被超额分配(overcommit),最终节点级 OOM 或大量 Pod 被驱逐。

2. limits 设置过小

应用实际需要 800Mi,limits 只给了 512Mi。进程一旦增长到 512Mi 就被 cgroup OOM killer 杀掉,表现为反复 CrashLoopBackOff + OOMKilled。

3. requests 与 limits 相等

这种配置会让 Pod 进入 Guaranteed QoS 等级,节点内存紧张时最后被驱逐,通常是最稳妥的选择,但需要准确评估用量。

QoS 等级如何影响被杀的优先级

Kubernetes 按 requests/limits 把 Pod 分为三档,节点内存压力下的驱逐顺序是:

  1. BestEffort:所有容器都没有设置 requests 和 limits,最先被驱逐。
  2. Burstable:设置了但不相等,中间档。
  3. Guaranteed:每个容器的 CPU/内存 requests 都等于 limits(且都设置了),最后被驱逐。

注意:QoS 影响的是节点级驱逐的优先级,而容器级 OOM 由容器自己的 cgroup limit 决定,两者是不同层面的机制。

被 OOMKilled 之前发生了什么

  1. 容器内进程申请内存,cgroup 记账接近 memory.max。
  2. 超过 limit 时,内核先尝试回收(page cache 等),回收不动就进入 cgroup OOM。
  3. 内核 OOM killer 在该 cgroup 内按 oom_score 选进程杀掉(通常选内存占用最大的)。
  4. 容器主进程死亡,kubelet 按 restartPolicy 重启容器,kubectl describe pod 中出现 Last State: Terminated, Reason: OOMKilled。

排查与调整建议

确认是否真的 OOM:

kubectl describe pod <pod-name> | grep -A5 'Last State'
kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[*].lastState}'

看实际用量: 用 kubectl top pod(依赖 metrics-server)或容器内 cat /sys/fs/cgroup/memory.max(cgroup v2)/ memory.limit_in_bytes(cgroup v1)核对 limit 值。

调整原则:

  • 先观察一段时间的实际内存峰值,再设置 limits,留出合理余量(如峰值的 1.2~1.5 倍)。
  • requests 尽量贴近稳态用量,避免调度过度乐观。
  • 对内存敏感的服务,优先采用 requests = limits 的 Guaranteed 配置。
  • 不要为了“省事”把 limits 设得极大,那等于把风险从容器转移到节点。

一句话总结

OOMKilled 是结果,requests/limits 错配是原因之一。理解 requests 管调度、limits 管运行时上限、QoS 管驱逐顺序这三层分工,才能把内存问题定位在正确的层面。

评论(0)

  • 还没有评论,来抢沙发~

相关文章