写点什么

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

  • 2025-08-27
    北京
  • 本文字数:3015 字

    阅读完需:约 10 分钟

大小:1.48M时长:08:35
OOM 杀进程 or 应用卡顿?该如何抉择

背景


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


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

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


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


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

为什么还不 OOM?


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

(图/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

内存用量,iowait、sys等指标

节点、cgroup、pod

单进程或进程组

systemd-oomd

cgroupV2

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

cgroup

杀整个cgroup

(表/FastOOM 与 oomd 对比)

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

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


客户遇到的问题


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



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



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



解决方案


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



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


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



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

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


客户遇到的问题


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


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


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



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


解决方案


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


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


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


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

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

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


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


总结


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


联系我们 


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

操作系统控制台钉钉交流群


阿里云操作系统控制台 PC 端链接:

https://alinux.console.aliyun.com/

2025-08-27 15:244420

评论

发布
暂无评论

管理技巧 | 提升团队效能:如何与下属进行有效沟通

测吧(北京)科技有限公司

测试

MATLAB R2023b提示已停止工作怎么办?

Rose

数学软件 MATLAB R2023b

如何将应用一键部署至多个环境?丨Walrus教程

SEAL安全

MySQL 运维 应用部署 Walrus

探索AI的边界:如何精准地测试人工智能

测吧(北京)科技有限公司

测试

提升团队效能:如何与下属进行有效沟通

霍格沃兹测试开发学社

LLM 大模型框架 LangChain 可观测性最佳实践

心有千千结

观测云 LLM langchain

一文读懂私网解析 PrivateZone

火山引擎边缘云

DNS DNS服务器 DNS劫持 #DNS

一键Run带你体验扩散模型的魅力

华为云开发者联盟

人工智能 华为云 华为云ModelArts 华为云开发者联盟

云服务和本地部署大对比,应该选择哪种方式?

Finovy Cloud

云计算 云服务器 云部署搭建

AI数字虚拟人来了你会失业吗?

小魏写代码

益和热力选择 TDengine,实现智慧供热系统升级

TDengine

tdengine 时序数据库

Sibelius西贝柳斯2023 mac永久使用 兼容M1/M2

Rose

Avid Sibelius 2023 Mac 西贝柳斯 Avid Sibelius

Shell 检查程序进程是否存在,自动重启

最爱小胖子

软件测试团队管理技巧 | 提升团队效能:如何与下属进行有效沟通

测试人

软件测试

国家科技传播中心讲坛!播出预告:吴甜——当机器学会思考

飞桨PaddlePaddle

人工智能 深度学习 百度 BAIDU 百度飞桨

深入浅出:JavaScript 中 every() 的运作原理

Apifox

JavaScript 程序员 前端 数组 前端开发

春天已至,见证80/90/00后女性开发者的云上生长力量

华为云开发者联盟

人工智能 华为云 科技 华为云开发者联盟 先锋开发者云上说

文心一言 VS 讯飞星火 VS chatgpt (210)-- 算法导论16.1 1题

福大大架构师每日一题

福大大架构师每日一题

[自研开源] MyData 数据集成任务的流程介绍 v0.7.1

LIEN

开源 数据集成 业务融合 API对接 mydata

大咖公开课 | 探索AI的边界:如何精准地测试人工智能

霍格沃兹测试开发学社

OOM 杀进程 or 应用卡顿?该如何抉择_操作系统_肖杰韬_InfoQ精选文章