这类问题我又碰上了一次。一台 8 核 16G 的 Ubuntu 22.04 跑容器化采集程序,容器内存涨到 6G 后处理速度掉到原来五分之一,dmesg 里没有任何 OOM 记录,free 看宿主机还剩 5G。
第一反应是「业务把页缓存也算进 cgroup,文件读写多时额度被缓存占满」,验证下来不成立。
这类报错背后常见的原因有几处,逐个排除就行。cgroup v2 的 memory.high 是软上限,超过后内核节流而不是杀进程,现象就是整体变慢;memory.current 长期贴着 high 值,回收压力全落在该 cgroup 上;memory.stat 里的 pgscan 增长快,说明一直在直接回收。
第一件事是看容器 cgroup 的当前值与水位
cat /sys/fs/cgroup/system.slice/docker-*.scope/memory.current /sys/fs/cgroup/system.slice/docker-*.scope/memory.high
然后确认是否在频繁直接回收
grep -E 'pgscan_direct|pgsteal_direct' /sys/fs/cgroup/system.slice/docker-*.scope/memory.stat
随后把软限提到与硬限一致,先解除节流
echo 8G > /sys/fs/cgroup/system.slice/docker-*.scope/memory.high
从容器启动参数上固定限额
docker update --memory 8g --memory-swap 8g collector
怎么算真的好了,看的是同一批现象。memory.current 稳定低于 memory.high,pgscan_direct 不再持续增长,采集速度回到原来水平且 dmesg 中仍无 OOM 记录。
memory.high 造成的性能下降很难从日志里看出来,只能靠 cgroup 指标;设限额时要给页缓存留余量,压到贴着业务峰值一定会节流。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。