kubectl describe pod order-api-7f9c | grep -A 5 'Last State' java -XX:MaxRAMPercentage=65 -XX:MaxMetaspaceSize=256m \ -XX:MaxDirectMemorySize=256m -jar app.jar
Pod 每两小时重启一次,kubectl describe 里 lastState 是 OOMKilled,exit code 137,容器 limit 2Gi,启动参数写的 -Xmx3g。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:JVM 堆上限比容器内存还大,堆涨到 2G 附近时加上元空间、线程栈和直接内存就超过 cgroup 限制,内核直接杀进程。JDK 8 早期还不认 cgroup 限制。
这次卡住的地方就在「容器 JVM 堆超限」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。
处理上按这个顺序:把 -Xmx 调到 limit 的 60% 到 70% 留出堆外空间;用 -XX:MaxRAMPercentage=65 让 JVM 自己按 limit 算;配 -XX:MaxMetaspaceSize 和 -XX:MaxDirectMemorySize 卡住其余部分;观察一周 RSS 峰值再微调。
确认没问题再收工,连续运行 24 小时 Pod 重启次数为 0 RSS 峰值保持在 1.9G 以下。
