OOM 杀进程 or 应用卡顿?该如何抉择 原创

阿里云基础软件
发布于 2025-8-27 18:04
浏览
0收藏

背景

近期,大量用户反馈系统在运行过程中出现CPU利用率与系统负载(load)突发性飙升,甚至引发系统短时卡顿(持续数秒至数十秒)的问题;对于业务来说,轻则导致几百毫秒的抖动,重则连机器都无法ssh上去。经分析发现,此类异常现象普遍存在一个显著特征:均发生在系统内存占用率接近阈值(90%-95%)时。用户就发出了灵魂拷问:

“水位这么高了,为什么内核不触发OOM杀掉一些进程来释放内存?"

“我宁愿内核OOM把我业务进程杀了,我也不希望应用卡顿和系统夯机影响我其他业务!”

其实这个现象的核心原因就是:内核想确保应用实在没内存用了才OOM!

思想总体是正确的!但是一条思想要满足所有场景也是非常难的!

为什么还不OOM?!

内存水位这么高,为什么还不OOM!其实主要是由于系统进入了Near-OOM状态。我们先回顾一下Linux的内存回收机制,如下图所示:

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

图/Linux内存水线

Linux划分了 high、low、min 三个内存水线。当系统剩余内存低于 low 水线后,内核会唤醒kswapd进程会被唤醒开始进行异步的内存回收,此时对系统没什么影响;系统剩余内存低于min水线后,内核会阻塞要分配的内存进程尝试尽可能地回收所有可回收的内存(主要是文件缓存以及一些内核结构体缓存),回收的过程中可能涉及到将文件缓存写入磁盘或遍历一些内核结构体,从而导致系统负载飙高、应用被阻塞。如果能成功回收内存并满足申请需求则不触发OOM。

更糟糕的是,系统可能进入一种Near-OOM的活锁状态,即内核一边在尝试回收文件缓存;但是应用运行过程中从磁盘加载代码段等行为也在不断产生文件缓存,那么就会使整个系统负载持续飙高,甚至发生夯机。

所以,内核OOM的策略在业务延时敏感的场景,还是太保守了!

那么如果我们希望宁愿OOM把我业务进程杀了,我也不希望应用卡顿和系统夯机影响我其他业务?还有什么办法呢?

新OOM方案

为了应对Near-OOM现象,核心就是“快”OOM,在内核还在犹豫要不要OOM的时候,我们就替他做出决定!目前业界已有的方案主要是通过用户态提前杀死相关进程来提前释放内存,比如应用较为广泛的是Facebook(Meta)推出的oomd。oomd目前已经集成于systemd中成为systemd-oomd,且从Ubuntu 22.04开始集成于Ubuntu中。但是oomd方案存在以下问题:

●与cgroupV2以及Linux内核的PSI(Pressure Stall Information)特性深度绑定。但cgroupV1目前仍然是云计算中主流cgroup版本,且由于PSI功能有一定的性能开销,在大部分云计算场景中都是默认关闭的。

●只支持以cgroup为粒度杀进程,配置cgroup级别的杀进程策略。

所以oomd在适用性和灵活性上仍有欠缺。

为了解决上述问题,阿里云操作系统控制台推出了FastOOM功能,支持节点以及Pod级别的用户态OOM配置,通过提前介入杀进程的方式避Near-OOM导致的抖动夯机。

FastOOM同样采取用户态提前杀进程的形式来避免系统进入Near-OOM状态,主要分为采集预测模块和kill模块:采集预测模块会从阿里云自研操作系统中读取内存压力相关的指标,通过统计学方法对OOM发生的概率进行实时预测并判定当前节点或pod是否达到相应的内存压力或即将进入Near-OOM状态。kill模块会根据用户配置的杀进程策略,选取对应的进程杀死。

最终所有由FastOOM执行的kill操作事件都会上报到控制台中心端进行展示,让用户方便了解底层的实际操作(不用担心FastOOM偷偷杀死了其他进程)。

 

cgroup版本支持

内存压力检测方法

支持粒度

杀进程粒度

FastOOM

cgroupV1

阿里云操作系统自研指标

节点、cgroup、pod

单进程或进程组

systemd-oomd

cgroupV2

主要基于内核PSI(pressure stall information),内存用量。

cgroup

杀整个cgroup

(表/FastOOM与oomd对比)

使用FastOOM避免Near-OOM系统夯机抖动

案例一:配置节点级别策略解决系统Near-OOM抖动夯机问题

客户遇到的问题

某汽车行业发现某实例上业务长时间无响应、登录实例也十分卡顿。通过监控发现客户实例使用的内存在某个时间点开始徒增,接近系统的总内存(即available非常低),但没有超过系统总内存。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

通过top命令可以看到系统的CPU sys利用率和iowait利用率和系统负载都持续飙高,kswapd0线程占用非常高的CPU进行内存回收。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

通过操作系统控制台的系统概览可以看到,在发生OOM夯(即处于Near-OOM状态)的同时,也发生了用户态收包延时,业务发生了抖动。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

解决方案

通过配置开启节点级别的FastOOM功能,由于业务是实验较为敏感的业务,内存压力选择中,且设置业务程序(以python启动,进程名包含python子串)为避免被OOM进程且设置无关的日志程序优先杀死。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

开启后,当节点内存水位处于near-OOM状态时,用户态提前介入,根据配置杀死了如下进程,从而释放了部分内存避免系统进入了夯机状态。通过操作系统控制台的系统概览可以看到FastOOM介入的相关记录

如下图所示,由于kube-rbac-proxy和node_exporter等进程oom_score_adj被设置为接近999,FastOOM会匹配内核策略优先杀死这些进程,但是由于杀死这些进程后释放内存较小,仍处于near-OOM;因此FastOOM杀死了配置优先杀死的logcollect进程。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

由于用户态及时介入杀死进程释放出内存,使系统避免进入了near-OOM的抖动状态。

案例二:配置Pod级别策略解决Pod应用抖动夯机问题

客户遇到的问题

在Kubernetes环境中,我们是可以为Pod中的容器配置对应的内存限制的。和节点OOM同理,如果Pod中的内存使用接近限制时。内核也会尝试回收Pod中所有可回收内存,才触发OOM,这时候也会导致Pod内业务进程的延时阻塞。

某大数据客户会部署一些延时敏感的业务pod(即pod中运行了多个业务进程)。业务时不时会存在响应长尾延时,但是网络相关指标一切正常。

后面我们接手问题后,通过Alibaba Cloud Linux OS自研指标(该指标反映容器由于内存回收阻塞的时长)发现,存在非常高的内存回收延时,且时间节点和抖动时间匹配:

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

推荐客户配置Pod级别的FastOOM后,通过提前杀死Pod中的相关内存占用进程,避免了内存回收延时的发生,抖动也不再出现。

解决方案

操作系统控制台提供较为灵活的Pod级别的OOM杀进程策略配置,可以灵活配置Pod中容器内发生OOM时,避免和优先杀死的进程。

假设在集群中通过名为test-alinux的daemonset在每一个节点部署了对应的pod。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

在操作系统控制台中设置Pod级别FastOOM策略:

● 为了匹配对应的pod,pod名称填写test-alinux(正则表达式会匹配不同节点上的test-alinux-xxx pod),命名空间为default。

●由于只是希望控制OOM时的杀进程策略,将内存压力级别设置为高,则触发用户态OOM的时机会近似于内核OOM的时机。

●对于杀进程策略:配置优先杀死特定进程和避免杀死业务进程和pod中的1号进程,从而避免pod重启或影响业务,设置完成后下发至特定节点。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

将配置下发到对应节点后,当Pod中容器内存使用超过容器limit后,发生OOM;可以通过操作系统控制台系统概览看到FastOOM事件记录,可以看到FastOOM根据策略杀死了对应的进程,也避免了特定进程被杀死。

OOM 杀进程 or 应用卡顿?该如何抉择-鸿蒙开发者社区

总结

人无完人,内核的OOM其实也不是万能的。为了能尽可能的回收内存,内核在发生OOM前会阻塞申请内存的进程,并尝试回收内存,这对于延时敏感的业务的影响是非常大的;如果内存持续保持在接近OOM的水位,还会进入Near-OOM的活锁状态导致整机夯机。阿里云操作系统控制台的FastOOM功能,通过相关指标,支持节点/容器/pod级策略,可精准杀指定进程,轻松弥补了内核OOM带来的延时卡顿问题。

 联系我们 

您在使用操作系统控制台的过程中,有任何疑问和建议,可以搜索群号:94405014449 加入钉钉群反馈,欢迎大家扫码加入交流。

阿里云操作系统控制台PC端链接https://alinux.console.aliyun.com/

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐