最可靠方式是用cgroups v2设memory.max并启用OOM killer;需确认启用v2、新建cgroup、写入PID、生产环境用systemd持久化配置。

直接用 cgroups v2 配置内存限制是最可靠的方式,核心是设置 memory.max 并启用 OOM killer,避免进程因内存超限被系统粗暴终止或拖垮整台机器。
确认系统使用 cgroups v2
旧版 cgroups v1 多挂载点、行为不一致,容易漏控;v2 是单层级统一管理,必须先确认已启用:
- 运行
mount | grep cgroup2,看到类似cgroup2 on /sys/fs/cgroup type cgroup2即为正常 - 检查
/sys/fs/cgroup/cgroup.controllers是否存在且非空(v1 下该路径不存在) - 若未启用:编辑
/etc/default/grub,在GRUB_CMDLINE_LINUX中追加cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1,再执行sudo update-grub && sudo reboot
创建独立 cgroup 并设内存上限
不要复用默认根组,应新建专用目录,显式启用 memory 控制器:
- 创建控制组:
sudo mkdir /sys/fs/cgroup/mycontainer - 启用 memory 控制:
echo "+memory" | sudo tee /sys/fs/cgroup/mycontainer/cgroup.subtree_control - 设硬性内存上限为 2GB(含缓存与匿名页):
echo 2G | sudo tee /sys/fs/cgroup/mycontainer/memory.max - 可选:允许触发 OOM killer 而非挂起进程:
echo 1 | sudo tee /sys/fs/cgroup/mycontainer/memory.oom.group(推荐开启)
将容器进程纳入该 cgroup
关键不是“启动时指定”,而是确保容器主进程 PID 写入 cgroup.procs(迁移整个线程组):
- 查出容器主进程 PID,例如:
docker inspect -f '{{.State.Pid}}' myapp - 写入控制组:
echo $PID | sudo tee /sys/fs/cgroup/mycontainer/cgroup.procs - 验证是否生效:
cat /sys/fs/cgroup/mycontainer/cgroup.procs应显示该 PID;cat /sys/fs/cgroup/mycontainer/memory.current可实时查看已用内存
生产环境建议用 systemd 持久化
手动写 sysfs 易丢失,适合调试;长期运行务必通过 systemd 管理:
- 为容器服务单元(如
/etc/systemd/system/myapp.service)添加: [Service]MemoryMax=2G-
MemoryLimit=2G(兼容性更强) -
OOMPolicy=kill(明确 OOM 行为) - 重载并启用:
sudo systemctl daemon-reload && sudo systemctl restart myapp
不复杂但容易忽略:memory.max 设为 0 会立即触发 OOM kill;设为 max 则无限制;数值单位支持 K/M/G,无需换算字节。











