文章背景图

Linux 服务器频繁 OOM:从现场证据、内存泄漏到容量治理

2026-08-08
0
-
- 分钟

OOM 不是“内存使用率高”这么简单。它表示内核或容器在满足内存分配请求时无法继续,只能选择进程终止。处理 OOM 的关键是区分宿主机 OOM、cgroup OOM、应用主动退出和 Kubernetes OOMKilled。

一、确认是否真的发生 OOM

journalctl -k --since '-2 hours' | grep -Ei 'out of memory|oom|killed process'
dmesg -T | grep -Ei 'out of memory|oom|killed process'

记录发生时间、被杀进程、进程内存、cgroup、节点剩余内存和当时业务流量。Kubernetes 中继续查看:

kubectl describe pod <POD> -n <NS>
kubectl get pod <POD> -n <NS> -o jsonpath='{.status.containerStatuses[*].lastState}'

退出码 137 只是收到 SIGKILL 的常见表现,需要结合事件确认是否 OOMKilled。

二、理解关键内存指标

free -h
cat /proc/meminfo
vmstat 1 10
ps -eo pid,user,%mem,rss,vsz,cmd --sort=-rss | head -30

不要把 free 列很小直接理解为内存不足,Linux 会利用空闲内存做缓存,应重点看 available。RSS 表示进程实际驻留内存,VSZ 包含虚拟地址空间,不能单独用来判断泄漏。

三、确认谁在增长

pidstat -r 1 20
pmap -x <PID> | tail -20
cat /proc/<PID>/status
cat /proc/<PID>/smaps_rollup

连续观察比单次快照更重要。若 RSS 随请求持续增长且业务低峰不回落,可能存在堆、直接内存、线程栈、本地缓存或内存映射泄漏。Java 应保留 heap dump 和 GC 日志;Go 可使用 pprof;Python 可结合 tracemalloc 分析。

四、检查 cgroup 和容器限制

cat /sys/fs/cgroup/memory.current 2>/dev/null
cat /sys/fs/cgroup/memory.max 2>/dev/null
cat /sys/fs/cgroup/memory.events 2>/dev/null

宿主机还有大量内存,并不代表容器不会 OOM。容器达到自身上限时会触发 cgroup OOM。Kubernetes 的 request 用于调度,limit 才是上限;limit 设置过低会频繁 OOM,设置过高则可能造成节点超卖和抖动。

五、检查内核内存与缓存

slabtop
cat /proc/meminfo | grep -E 'Slab|SReclaimable|SUnreclaim|PageTables'

大量连接、目录项、inode、网络缓冲区和内核对象也会消耗内存。不要在生产环境把 drop_caches 当作长期方案,它只能暂时释放可回收缓存,无法修复泄漏和容量不足。

六、紧急止血

  • 摘除异常实例并保留证据;

  • 临时扩容或降低并发;

  • 回滚最近发布;

  • 限制批任务和大查询;

  • 在风险可控时重启泄漏进程;

  • 避免同时重启整个集群造成雪崩。

七、长期治理

  • 监控工作集、RSS、堆、直接内存、GC、cgroup 事件和 OOM 次数;

  • 根据压测与历史峰值设置 request/limit;

  • 为缓存设置数量和大小上限;

  • 建立 heap dump、pprof 等现场采集机制;

  • 进行容量评估,保留节点和系统组件安全余量。

总结

OOM 排查必须回答三个问题:谁被杀、为什么达到上限、增长来自哪里。只有把内核日志、进程内存、容器限制和业务变化串联起来,才能从“重启恢复”走向真正防复发。

原创

Linux 服务器频繁 OOM:从现场证据、内存泄漏到容量治理

本文链接: Linux 服务器频繁 OOM:从现场证据、内存泄漏到容量治理

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录