.NET容器触达内存限制后CPU占满100%问题排查咨询
禁用swap环境下带内存限制的.NET容器CPU资源占满问题
问题现象
在openSUSE Tumbleweed(MicroOS)系统上运行配置了内存限制的.NET容器时,例如执行podman run --memory 32m xxx命令启动容器,当容器内程序运行达到内存上限后,短时间内就会占用几乎全部可用CPU资源,多数情况下该异常状态会持续存在,直到手动终止进程。
部分场景下进程会如预期被OOM机制杀死,但绝大多数情况下进程会持续运行、空耗CPU周期,成为影响同节点其他负载的吵闹邻居。
目前初步推测问题成因为:垃圾回收器(GC)持续消耗全部CPU资源尝试回收/释放内存导致的——GC错误判定仍有可申请的内存空间,但在其他发行版/内核/操作系统环境下,GC会收到“无剩余内存可分配,无论如何尝试都无法获取更多内存”的明确反馈。
已完成验证项
- 若启用swap分区,该问题基本会消失。该问题最初在Kubernetes环境中发现(Kubernetes节点默认应禁用swap),为排除环境复杂度影响,已通过podman完成问题复现。
- 最初曾在openSUSE社区提交该问题,当时误认为问题仅出现在openSUSE Tumbleweed系统上,后续才发现问题触发诱因是MicroOS发行版默认禁用swap。
- 在基于Java的容器(例如Jenkins)上也观察到过同类问题,但据已观测记录,Go语言编写的应用从未出现该问题,因此推测该问题与.NET/Java采用的垃圾回收机制存在关联。
- 曾尝试采集转储文件(
dotnet counters/gcdump)分析进程运行状态、确认是否在执行GC操作,但始终未能成功:进程似乎处于某种锁死状态,执行转储采集操作时会直接挂起。 - 该问题在Server GC和Workstation GC模式下均会出现。
- .NET 5/6版本已支持cgroupsv2,最早在.NET 2.1版本(该版本不支持cgroupsv2)就遇到过该问题,但等待.NET官方支持cgroupsv2后问题并未解决;也曾尝试禁用cgroupsv2,分别使用runc、crun容器运行时测试,问题依然存在。
已开展排查动作
- 已查阅.NET、容器、cgroupsv2相关的OOM问题公开资料,未找到有效解决方案。
- 曾考虑调整GC相关配置参数,但在未明确问题根因的情况下盲目调参效率极低。
- 已编写可复现该问题的简单.NET程序,逻辑为持续申请分配内存,项目仓库内包含可用于构建镜像的Dockerfile,可通过
podman build -t xxx .命令构建测试镜像。
诉求
希望能得到相关方向指引,明确问题根因以及对应的可行解决方案。
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

