Java k8s pod 经常重启问题

2023-09-17 22:33:49 +08:00
 dunhanson

1 、程序没有发生堆内存异常

2 、内存显示(Memory Usage (bytes)一直在增加( kubernetes dashboard )

3 、jvm 参数设置 JAVA_TOOL_OPTIONS

-XX:+UseContainerSupport -XX:InitialRAMPercentage=80.0
-XX:MaxRAMPercentage=80.0 -XX:+PrintGCDetails
-XX:+PrintGCDateStamps -Xloggc:/data/logs/app/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/logs/app/dump.hprof
3421 次点击
所在节点    Kubernetes
45 条回复
cdlnls
2023-09-18 15:24:41 +08:00
notwaste
2023-09-18 15:25:43 +08:00
看描述是 OOM Killer 的问题,容器是否有其他程序占用内存,站内搜下 OOM Killer 可能会有些收获
anubu
2023-09-18 15:42:48 +08:00
可以看看 #20 的回复。我们在 k8s 环境碰到过这个问题,JDK8 和 cgroup2 有兼容性问题,无法识别容器的 limit 导致 OOM 。可以考虑升级 JDK ,降级 cgroup ,手动指定 xmx 等方法。
julyclyde
2023-09-18 18:20:41 +08:00
@anubu 我觉得这个东西不能叫“有兼容性问题”;写成“未考虑与 cgroupv2 的兼容性”比较好吧
julyclyde
2023-09-18 18:22:05 +08:00
@anubu 我觉得这个东西不能叫“有兼容性问题”;写成“未考虑与 cgroupv2 的兼容性”比较好吧
v2nika
2023-09-18 18:52:33 +08:00
kubectl describe pod YOUR_POD_NAME

可以看到 restart 的原因.
v2nika
2023-09-18 19:02:40 +08:00
有一种情况是 pod 被驱逐了, 会导致 pod 名字变了, 就找不到了, 可以通过 kubectl get events 查一下事件记录.

另外还有可能是 node 内存不够导致 pod 被系统 oom 杀掉了 (我猜大概率是这个), 这个时候是找不到任何日志的, 因为 jvm/kubelet 都没有机会记录这个事件. 发生的原因是你的 memory 的 request 和 limit 写的不一样, memory 属于不可压缩资源, k8s 没有办法在已经申请后调度. 另外你的 cpu limit 配置的是 4, 这个时候的 gc 算法默认是 G1 (<= 1 的时候是 Serial GC), G1 会在达到你配置的最大堆内存的一个比例前持续增加 old gen 的内存占用 (即使这些对象已经没有引用), 直到发生 mixed gc 或者 full gc.
v2nika
2023-09-18 19:05:31 +08:00
不过我看你的 InitialRAMPercentage 配置和 MaxRAMPercentage 配置一样, 不太可能是上面说的那个.
julyclyde
2023-09-18 22:07:37 +08:00
@v2nika oom 的时候,在那个 node 自己的 dmesg 里是有日志的
dunhanson
2023-09-18 22:16:24 +08:00
@matepi 我看的一篇阿里云官方的资料上面这么推荐配置的,就我这个程序有这个问题,我看其他同事一样的配置,没啥问题 哈哈
dunhanson
2023-09-18 22:17:12 +08:00
@Georgedoe 写了容器支持:UseContainerSupport
dunhanson
2023-09-18 22:21:30 +08:00
@v2nika
Reason: OOMKilled
Exit Code: 137
dunhanson
2023-09-18 22:23:08 +08:00
@cdlnls 我用 arthas 看了下,最大堆内存:5426M ,符合 75%设置,有生效
dunhanson
2023-09-18 22:26:30 +08:00
@notwaste 只有 java 一个进程
Goooooos
2023-09-18 22:32:33 +08:00
我的内存最大都只设置到 70%,你 80%的话,如果 POD 内存不大,那剩余的内存不多了,可能一些堆外内存就容易占满。建议根据实际情况调整。
YzSama
2023-09-18 22:50:39 +08:00
1 建议升级 11 ,2 最好的方式是容器自适应。我之前也是,后面不设最大 max 和 min 了。基本不会重启了
cheng6563
2023-09-18 22:59:50 +08:00
你 Java 服务没用 jni 那些 native 内存管理的话,只靠-Xmx 限制就够用了,k8s 的 pod 限制可以去掉或者设置很大。
beiluo
2023-09-19 10:08:54 +08:00
@dunhanson #33 看了下 arthas 的截图,可以考虑把 Xmx 的 75%降到 50%左右试试,可能会增加一些 GC 频率,但是服务更稳定。一个 docker 容器里面会有 Linux 系统本身的占用+JVM 堆占用+JVM 堆外占用(包括 metaspace ,code cache ,native 等)堆占用 75%之后,其实留给其他部分的并不多了。个人理解。
cmai
2023-09-19 11:20:52 +08:00
看不到阿尔萨斯的图了,从堆外内存泄漏着手吧
notwaste
2023-09-19 14:22:00 +08:00
https://www.v2ex.com/t/740570

“问题出发点不在修改方便上面,Xmx 跟容器平台 memory limit 不契合是关键。因为 JVM 进程内存不严格的说要等于 Xmx + 线程数 * Xss + native allocation 等等等,如果 Xmx 是设置好的,跟 limit 一样,实际上堆内存还远没用到 Xmx 就会到达 memory limit 被 kubernetes exit 137 这个值必须要动态”

可以看下 7 楼里面引用的答案和评论

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/974651

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX