最可靠做法是将关键进程oom_score_adj设为-1000实现内核级免杀,再结合cgroup v2限制非关键进程内存、调优vm.panic_on_oom等内核参数,并部署earlyoom前置干预,形成分层防护体系。

关键业务进程(如数据库、API网关、消息队列)在内存紧张时被OOM Killer误杀,是生产环境高频故障源。最可靠的做法不是阻止OOM发生,而是确保关键进程在OOM事件中绝对不被选中——核心手段是将 oom_score_adj 设为 -1000,同时辅以分层防护机制。
给关键进程设死免杀权重:oom_score_adj = -1000
这是内核级硬保障:值为 -1000 表示该进程在全局 OOM 事件中被跳过,不会进入评分和终止流程。
- 对已运行进程:获取 PID 后立即写入
echo -1000 | sudo tee /proc/<PID>/oom_score_adj - 对 systemd 服务(推荐长期配置):
执行sudo systemctl edit <service-name>,添加:
[Service]
OOMScoreAdjust=-1000
- 重载生效:
sudo systemctl daemon-reload && sudo systemctl restart <service-name> - 典型建议值参考:
• sshd、journald:-1000(保运维通道)
• MySQL/PostgreSQL:-500 至 -800(留弹性,防系统失控)
• Nginx/Envoy:-300(强保护但不过度)
隔离非关键进程,防内存溢出拖垮节点
单靠保护关键进程不够,必须限制低优先级任务的内存上限,避免其突发占用耗尽资源。
- 用 cgroup v2 限制后台任务:
sudo mkdir -p /sys/fs/cgroup/low-priorityecho "max 512M" | sudo tee /sys/fs/cgroup/low-priority/memory.maxecho <PID> | sudo tee /sys/fs/cgroup/low-priority/cgroup.procs - 对 cron 脚本或监控工具,启动前加内存约束:
ulimit -v 2097152 && ./backup.sh(限制虚拟内存 2GB) - Java 应用必须设
-Xmx,且不超过物理内存的 70%,K8s 环境额外启用-XX:+UseContainerSupport
调优内核OOM行为策略,让决策更可控
默认 OOM 行为偏激进,需调整为更可预测、更公平的响应方式。
- 确认关键参数:
vm.panic_on_oom=0(禁用整机 panic,只杀进程)vm.oom_kill_allocating_task=0(不直接杀申请者,按综合得分选目标,对数据库事务更友好) - 降低虚假 OOM 概率:
设vm.overcommit_memory=2,配合vm.overcommit_ratio=85,即最多允许申请物理内存 × 0.85 + swap 总量 - 配置方式:
写入/etc/sysctl.d/99-oom.conf,再执行sudo sysctl -p
前置干预:部署 earlyoom 作为缓冲防线
原生 OOM Killer 是“最后一搏”,earlyoom 可在内存真正耗尽前主动介入,为关键服务争取优雅降级时间。
- 安装后配置触发阈值:
可用内存 ≤ 8% 时发送SIGTERM(支持 graceful shutdown)
≤ 4% 时才发SIGKILL - 与 systemd 集成,开机自启并日志跟踪,避免 silent failure
- 注意:它不替代 oom_score_adj,而是双保险中的第一道闸口


















