线上服务半夜被 OOM Killer 杀掉,查 dmesg 才发现是它干的,这种事遇到一次就够受。OOM Killer 不是随机杀人,它按 oom_score 挑,而这个分数我们是可以干预的。
一、先看 dmesg 还原现场。dmesg 里会写清楚当时内存水位、哪个进程被选中、它的 RSS 和 oom_score。先确认是真的物理内存耗尽,还是某个进程内存泄漏把系统拖垮的。泄漏问题靠调 OOM 参数是治标,真正要修的是泄漏本身。
二、给关键进程加保护。echo -1000 到 /proc/进程号/oom_score_adj 可以让 OOM Killer 基本不选它,但别滥用:保护了数据库,主进程没内存照样起不来。我的做法是只保护一两个真正不能死的进程,比如数据库主进程和监控 agent,其余交给分数排序。
三、用 cgroup 把内存框起来。systemd 的 MemoryMax 或者 cgroup v2 的 memory.max 可以给每个服务设上限,单个服务泄漏只会杀自己,不会拖垮整机。配合 MemoryHigh 做软限额,先节流再硬杀,给运维留出告警窗口。
四、留好应急余量。vm.min_free_kbytes 别设得太小,内核连应急内存都没有,OOM Killer 触发时系统可能已经卡到连日志都写不出来。交换分区不是摆设,关键时刻它能争取几分钟的排查时间,虽然会慢,但比直接杀进程强。
你们有没有被 OOM Killer 误杀过关键服务?最后是靠调分数、cgroup 还是修泄漏解决的?