Linux cgroups v2 内存限制怎么验证:memory.high、memory.max 与 OOM 事件逐项核对
来源:17golang原创
时间:2026-08-26 23:11:10 304浏览 收藏
服务明明没有把宿主机内存吃满,容器却突然退出,日志里还出现了 OOMKilled。这类问题通常不是“机器没内存”这么简单,而是进程撞上了自己所在 cgroup 的限制。cgroups v2 里,memory.high、memory.max 和 memory.events 各自记录不同层次的压力,必须放在同一条证据链里看。
先看
memory.current与两个阈值的关系,再用memory.events判断是回收/限速还是触发了硬上限;只有看到oom_kill增长,才能确认 cgroup 内发生过 OOM 杀进程。
memory.high是压力线,超过后会回收并可能让任务变慢,不等于立即杀进程。memory.max是硬上限;无法回收时才会进入 cgroup OOM 路径。memory.current要和memory.events的计数一起读取,单看某一刻的数值不够。- 复查时保留限制文件、事件计数和进程退出时间,避免把宿主机指标当成容器证据。
先把 cgroups v2 的三条内存证据放到一起
下面以一个名为 demo-worker 的层级说明。实际环境中,Docker、containerd 或服务管理器可能把服务放在更深的目录里,先确认进程的 cgroup 路径,再读取对应目录。
cat /proc/$(pgrep -n demo-worker)/cgroup
cg=/sys/fs/cgroup/demo-worker
cat "$cg/memory.current" "$cg/memory.high" "$cg/memory.max"
cat "$cg/memory.events"
memory.current 是当前用量,memory.high 是触发内存压力控制的边界,memory.max 是不可突破的硬限制。文件显示 max 时表示该层级没有设置对应上限;它不代表整个主机没有上限。

| 文件 | 它回答的问题 | 不要误读成 |
|---|---|---|
memory.current | 现在用了多少内存 | 已经发生 OOM |
memory.high | 何时进入压力控制 | 达到后必然杀进程 |
memory.max | 该层级的硬上限 | 宿主机总内存 |
memory.events | 压力与 OOM 事件是否累计发生 | 当前瞬时用量 |
memory.high 超过后,为什么进程只是变慢
当用量越过 memory.high,内核会对该 cgroup 施加内存压力控制,任务可能在分配内存时被延迟,并触发回收。它更像“限速线”,不是直接的 kill 开关。因此,接口延迟突然拉高但进程仍然存活时,先看这条线和 high 计数。
awk '$1 ~ /^(high|max|oom|oom_kill)$/ {print}' "$cg/memory.events"
cat "$cg/memory.pressure"
如果 high 持续增加,而 oom_kill 不变,现象更接近回收和节流。这里别急着把 memory.high 调大:先确认工作负载是否存在缓存无界增长、批量读取没有分段,或子进程没有退出。
memory.max 与 OOM 事件如何交叉验证
当回收无法把用量压回 memory.max 以下,cgroup 才会进入 OOM 处理。此时应保存事件计数和应用日志,而不是只凭一次 docker ps -a 的退出状态下结论。
before=$(awk '$1=="oom_kill" {print $2}' "$cg/memory.events")
date -Is
cat "$cg/memory.current" "$cg/memory.max"
cat "$cg/memory.events"
printf 'oom_kill_before=%s\n' "$before"
重点看 oom、oom_kill 和 oom_group_kill 是否增长。不同内核版本和工作负载下,事件字段的具体组合可能不同,但 oom_kill 增长是确认“cgroup 杀过进程”的关键证据。把这次输出和服务退出时间对齐,才能排除应用自己调用 exit、健康检查失败或上层编排器重启。

一套适合线上复盘的检查顺序
- 确认层级:从目标 PID 的
/proc/PID/cgroup找到实际 cgroup 目录,避免读取了父层或另一个容器的指标。 - 记录阈值:保存
memory.high、memory.max与采样时间;不要把max当成无限资源承诺。 - 记录当前值:连续采样
memory.current,观察是否在回收后下降,还是一直贴着硬上限。 - 核对事件:前后对比
memory.events;high增长提示压力控制,oom_kill增长才支持 OOM kill 判断。 - 对齐上层记录:把事件时间与应用日志、容器退出原因、编排器重启记录对齐,再决定是降峰、修复泄漏还是调整限制。
调整参数前,先把采样结果保存到故障单。否则重启容器后事件计数可能随层级销毁而丢失,之后只能凭印象争论“到底是不是内存杀”。
cgroups v2 内存限制常见问题:看懂数字,却看错了对象
宿主机 free 还有很多,为什么容器仍会被杀?
宿主机可用内存和 cgroup 上限是两套边界。容器可以在主机还有余量时先撞上自己的 memory.max。
memory.high 增长是不是 OOM?
不是。它更常说明任务经历了内存压力控制。需要继续看 oom_kill 等事件是否增长。
把 memory.max 调大就能解决吗?
不一定。若根因是缓存或批处理无界增长,调大只会推迟故障,还可能把压力转移给宿主机。先用采样确认增长对象。
结论:用“阈值、当前值、事件计数”闭环判断
cgroups v2 的排查重点不是背参数,而是让三类证据互相印证:阈值说明边界,memory.current 说明此刻的占用,memory.events 说明压力和 OOM 是否累计发生。这样才能把“服务变慢”“容器重启”和“cgroup 杀进程”分成三个不同问题,后续的容量调整才有依据。
-
426 收藏
-
387 收藏
-
242 收藏
-
133 收藏
-
496 收藏
-
489 收藏
-
484 收藏
-
405 收藏
-
252 收藏
-
462 收藏
-
134 收藏
-
351 收藏
-
492 收藏
-
411 收藏
-
328 收藏
-
164 收藏
-
493 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习