K8S system OOM 和资源配置实践

背景

我们目前服务是托管在 Aws K8S 的,近期出现了一次由于生产环境流量增大而导致的 system OOM 问题,进而导致了部分核心业务受损。在此之前,团队并没有思考过关于 K8S 资源配置上存在的一些问题,也没有按照业务自身情况使用对应的 QoS 类,从而导致了故障的产生。

本文将从这个角度切入,对 K8s 中的资源属性以及 QoS 进行介绍,最后给出生产环境使用的一些建议。

CPU 和 MEMORY 资源

不知道你是否有考虑过这样一个问题,为什么 CPU 可以超卖,而 Memory 不可以超卖? K8S 官方文档中对于水平扩容的默认机制也是基于 CPU 利用率的,而不是基于 Memory。

RAM differs significantly from CPU in that it’s an incompressible resource. That means we can’t just throttle your RAM usage, RAM is state!

什么是 incompressible resource?incompressible resource 意味着资源可以被节流(throttled)。这里,CPU 可以被认为是可压缩的,而内存是不可压缩的。当 Kubernetes 所管理的宿主机上不可压缩资源短缺时,就有可能触发 Eviction。比如,可用内存(memory.available)、可用的宿主机磁盘空间(nodefs.available),以及容器运行时镜像存储空间(imagefs.available)等等。

QoS

QoS:服务质量,Kubernetes 使用 QoS 类来决定 Pod 的调度和驱逐策略,即 宿主机资源紧张的时候,kubelet 对 Pod 进行 Eviction (即资源回收)时需要用到的。

下面这张表,笔者整理了 QoS 分类以及优缺点

QoS 解释 优缺点 备注 适用场景
Guaranteed POD 中的内存和CPU 必须指定,并且 request=limit - 缺失弹性能力,低谷期会有资源浪费- 可以规避 system oom 的出现,但不能保证容器 oom 稳定性优先的服务
Burstable Pod 中至少一个容器具有内存或 CPU 的请求或限制 - 有伸缩能力,一定程度上减少资源浪费- 当 limit 总和大于 node 可用资源时,会触发 system oom,意味着 Node is overcommitted。 按照 QoS 的划分条件,云端服务目前属于 Burstable。 稳定性要求较低的服务
BestEffort Pod 中的容器必须没有设置内存和 CPU 限制或请求 / 一般不考虑此场景,这里不讨论

此外,当内存不足时,POD 被驱逐的级别顺序是 BestEffort、Burstable、Guaranteed。

结合实际场景的思考和建议

对于我们实际的业务来看,我们一定是期望资源超卖以便于达到最大化的利用率,从而使得相应的成本能够节省下来。但是从 QoS 质量等级来看,是“鱼和熊掌”不可兼得的,所以需要做的就是找到一些平衡。

  • 期望:资源利用率最大化,资源超卖越多越好,这样可以节省更多的费用
  • 目标:关键业务要有一定的稳定性保障

在我们的场景中,服务可以分为核心和非核心两种,对于稳定性要求来说,核心服务要远高于非核心服务,所以得出的结论是:

  • 1、对于非核心服务,稳定性保障要求较低的服务,我们可以适当的超卖资源,从而获得资源更大程度的利用率;
  • 2、对于核心服务,则允许服务资源存在一定的浪费,优先保证服务稳定性。

参考

作者

卫恒

发布于

2022-12-04

更新于

2022-12-04

许可协议

评论