Linux OOM 怎么排查:区分内核、容器与服务内存限制

应用突然消失,重启后内存又恢复正常,这是 OOM 排查中常见的现场。Ubuntu 24.04 上,终止进程的可能是全局内存压力、某个控制组的限制,也可能是用户态内存管理策略。容器的退出码 137 通常表示与 SIGKILL 相关的退出,但仅凭这个数字不能证明一定发生 OOM,管理员或其他管理程序也可能发送同类信号。

先保留事件时间和进程身份

记录服务名、容器名、启动时间、退出时间和当时业务动作。不要一边持续自动重启,一边删除旧日志;这样会让每次失败的身份和时间难以对应。先从系统管理器取得退出原因,再核对应用日志中的最后一段。

在服务器运行:

sudo journalctl -k --since '30 minutes ago' --no-pager
systemctl status demo.service --no-pager
systemctl show demo.service -p Result -p ExecMainCode -p ExecMainStatus

替换实际服务名。内核日志中寻找 OOM、Killed process 或相关内存限制信息,同时保留前后文。服务自身返回错误、启动超时与内核终止,应按不同路径继续排查。

全机还有内存,也可能碰到局部上限

应用运行在容器或 systemd 服务控制组中时,可能先触发自己的内存上限,而整台机器仍有可用内存。查看服务配置:

systemctl show demo.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p ControlGroup
systemctl cat demo.service

MemoryHighMemoryMax 的作用不同,不能把两者当作相同的“最多能用多少”。还应检查父级 slice、容器平台和宿主机约束,因为实际有效范围不一定只来自这一份单元文件。systemd 资源控制手册解释了层级资源限制。

不要看到上限就直接设为无限。若其他服务依赖剩余内存,放开一个服务可能将局部故障扩大为整机压力。

用控制组事件增加证据

Ubuntu 24.04 常见的 cgroup v2 环境中,可以根据上一步实际 ControlGroup 路径读取 memory.events。不要凭服务名拼一个未确认的路径;容器、用户服务和系统服务所在层级可能不同。

关注 oomoom_kill 等计数,并与事件前后的采样比较。累计计数不自带完整业务上下文,单次看到非零值不等于刚才这次故障已经确认。父级事件还可能汇总下级变化,需要结合范围解释。Linux 控制组文档说明了各事件字段和层级行为。

短命容器或重建后的控制组可能已经失去现场,后续应把事件和内存趋势接入监控。只有故障结束后的截图,很难还原峰值来自并发、缓存还是单个异常任务。

检查用户态终止与实际压力来源

如果没有对应内核 OOM 记录,也要确认是否启用了 systemd-oomd,并查看它在同一时段的日志。它可以依据内存压力等条件提前采取动作,不能简单等同于内核已经分配失败。systemd-oomd 说明介绍了这种用户态机制。

继续对照进程内存、并发数量、批处理、导入、缓存和发布事件。应用的堆上限往往不包含全部进程内存,容器内数据库也不只占用一个缓存参数。分析时把稳定基线与短时峰值分开,避免用平均用量配置硬上限。

恢复后验证,避免无限重启掩盖故障

先恢复必要业务,可采用降低并发、暂停非关键批处理或增加经过评估的资源。调整上限前保留原值和配置备份,在相同负载下验证错误率、响应时间与内存曲线。不要把禁用 OOM 保护当成常规修复。

如果改动引发其他服务内存紧张,恢复原配置并重新分配负载。数据服务被终止后,还要检查事务恢复、任务重试和数据完整性;进程重新 running 不代表业务已经完整恢复。最终复盘应说明哪个范围触发了什么机制、哪类负载造成峰值,以及下次怎样提前发现。

参考资料

继续阅读

返回天理云文章中心

分享到:
上一篇
Linux swap 要不要开:内存压力判断与安全配置
下一篇
Linux 负载高但 CPU 不高?load average 与 iowait 排查
服务中心
企微客服
企微客服
给您高效服务
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意