Linux服务器内存管理实战:OOM Killer触发机制与cgroups内存限制配置

Linux服务器内存管理直接关系到服务稳定性。当系统可用内存耗尽时,OOM Killer会强制杀死进程以保护内核运行,生产环境常出现关键服务被误杀的问题。理解OOM Killer触发机制并配合cgroups做内存限制,是服务器运维中保障核心服务可用性的关键技能。

OOM Killer触发机制与评分规则

Linux内核在分配内存时采用超额承诺策略,物理内存不足时触发OOM Killer。OOM Killer通过oom_score对每个进程评分,选择分数最高的进程杀死。评分依据包括:内存占用大小、运行时间、nice值、是否为root用户、是否为内核线程等。

查看各进程OOM评分:

# 查看所有进程的oom_score
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
    score=$(cat /proc/$pid/oom_score 2>/dev/null)
    name=$(cat /proc/$pid/comm 2>/dev/null)
    echo "$score $pid $name"
done | sort -rn | head -20

# 查看进程详细oom_score_adj
cat /proc/$(pidof nginx)/oom_score_adj

oom_score_adj取值范围-1000到1000,值越大越容易被杀。设为-1000表示禁止OOM Killer杀死该进程,设为1000表示优先杀死。保护关键服务的配置:

# 保护Nginx主进程不被OOM杀死
echo -1000 > /proc/$(pidof nginx)/oom_score_adj

# 持久化配置,写入systemd service文件
# /etc/systemd/system/nginx.service
[Service]
OOMScoreAdjust=-1000

cgroups v2内存限制与隔离配置

cgroups v2将CPU、内存、IO等子系统统一到层级结构中,配置更简洁。通过cgroups限制容器或进程组的内存使用,防止单个服务耗尽系统内存导致全局OOM。

创建cgroup并设置内存限制:

# 启用cgroups v2
mount | grep cgroup2
# /sys/fs/cgroup type cgroup2 ...

# 创建应用cgroup
mkdir /sys/fs/cgroup/app_web
echo $$ > /sys/fs/cgroup/app_web/cgroup.procs

# 设置内存上限为4GB
echo 4294967296 > /sys/fs/cgroup/app_web/memory.max

# 设置内存软限幅为3GB,超过后优先回收
echo 3221225472 > /sys/fs/cgroup/app_web/memory.high

# 设置swap上限(v2中swap计入memory.max,可通过memory.swap.max单独限制)
echo 2147483648 > /sys/fs/cgroup/app_web/memory.swap.max

# 查看内存使用情况
cat /sys/fs/cgroup/app_web/memory.current
cat /sys/fs/cgroup/app_web/memory.events

memory.max设置硬上限,超出时触发cgroup内OOM Killer,只杀该cgroup内的进程;memory.high设置软上限,超出后内核优先回收该cgroup的内存页面,不直接杀进程。

systemd集成cgroups内存限制

生产环境通常通过systemd管理服务,systemd原生支持cgroups v2资源配置:

# /etc/systemd/system/webapp.service
[Service]
ExecStart=/usr/bin/python3 /opt/app/main.py
MemoryMax=4G
MemoryHigh=3G
MemorySwapMax=2G
MemoryDenyWriteExecute=yes

# CPU限制补充
CPUQuota=200%
CPUWeight=500

# IO限制补充
IOWeight=500
IOReadBandwidthMax=/dev/sda 50M

重载配置并重启服务:

systemctl daemon-reload
systemctl restart webapp

# 验证cgroup配置
systemctl show webapp -p MemoryMax -p MemoryHigh
systemd-cgls webapp

内存问题排查实战流程

当服务器发生OOM事件时,排查步骤:

# 1. 查看OOM Killer日志
dmesg | grep -i "killed process"
journalctl -k | grep -i oom

# 2. 查看被杀进程详情
dmesg -T | grep "Out of memory"

# 3. 使用smem查看进程实际内存占用(含PSS/USS)
smem -rs pss | head -20

# 4. 使用pidstat实时监控
pidstat -r 5

# 5. 抓取内存快照分析
# 在OOM触发前设置earlyoom或kernel panic dump
# /etc/sysctl.d/99-oom.conf
vm.panic_on_oom=0
vm.overcommit_memory=1
vm.overcommit_ratio=80

vm.overcommit_memory=1允许内核超额分配内存,配合cgroups做精确限制;vm.overcommit_ratio=80限制超额比例。earlyoom作为用户态OOM守护进程,可在内核OOM之前主动干预:

# 安装earlyoom
apt install -y earlyoom

# 配置:内存低于10%且swap低于10%时触发
# /etc/default/earlyoom
EARLYOOM_ARGS="-r 3600 -m 10 -s 10 --prefer '(java|python)' --avoid '(sshd|nginx|systemd)'"
systemctl enable --now earlyoom

通过OOM评分保护、cgroups内存隔离、earlyoom预干预三层机制,可以将内存耗尽时的影响范围控制在非关键服务内,避免关键进程被误杀导致服务不可用。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-fu-wu-qi-nei-cun-guan-li-shi-zhan-oomkiller-chu-fa-ji/

(0)
小编小编
上一篇 21小时前
下一篇 21小时前

相关推荐