dunhanson
V2EX  ›  Kubernetes

Java k8s pod 经常重启问题

By dunhanson at 2023 年 9 月 17 日 · 5008 次点击

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
第 1 条附言  ·  2023 年 9 月 18 日

pod

      resources:
        limits:
          cpu: '4'
          memory: 8G
        requests:
          cpu: 50m
          memory: 500m
第 2 条附言  ·  2023 年 9 月 18 日

JDK8版本:1.8.0_345

Reason: OOMKilled

Exit Code: 137

第 3 条附言  ·  2023 年 9 月 18 日

arthas

45 条回复  •  2023-12-15 13:24:02 +08:00
kevinlia0
   1
kevinlia0  
   2023 年 9 月 18 日 via Android
会不会是你分配给 pod 内存不够呢。
Frankcox
   2
Frankcox  
   2023 年 9 月 18 日
重启的时候看下事件或者 Pod 的 status ,或者你看 dashboard 看下内存是不是超了
ixx
   3
ixx  
   2023 年 9 月 18 日
看一下重启的时候 k8s 记录的 pod 日志 有没有 oomkilled
一般情况如果不是程序本身结束进程重启就是触发了 k8s 的 oomkilled 机制
beiluo
   4
beiluo  
   2023 年 9 月 18 日
大概率是 OOMKilled ,查看 pod status 可以看到 exit code 和 reason, exit code 可以参考 https://komodor.com/learn/exit-codes-in-containers-and-kubernetes-the-complete-guide/
如果不是,可以查看 previous pod log 看下是不是 jvm crash 出 core dump 了。
imyasON
   5
imyasON  
   2023 年 9 月 18 日
我遇到过,也是不知道什么原因。我容器内存是 1 - 2G ,Java -Xms xmx 设置的都是 2g, 然后 OPTIONS 加了一个 gc 类型 UseG1GC 。上线后出现和你一样的情况,莫名其妙的重启,后来我把-Xms1500m -Xmx1500m 和 gc 删掉让它用默认的,目前算是恢复正常,没有重启了。
fisherwei
   6
fisherwei  
   2023 年 9 月 18 日
java 版本是 1.8.191 以上吗?
jerry2233
   7
jerry2233  
   2023 年 9 月 18 日
`kubectl logs --previous POD_NAME`
dunhanson
   8
dunhanson  
OP
   2023 年 9 月 18 日
@kevinlia0 再怎么调大都会被重启
dunhanson
   9
dunhanson  
OP
   2023 年 9 月 18 日
@Frankcox
@ixx
@imyasON
我还得后续看下,目前没有发生重启,看下 pod 的推出状体码
dunhanson
   10
dunhanson  
OP
   2023 年 9 月 18 日
@fisherwei 最新版本的 jdk8
dunhanson
   11
dunhanson  
OP
   2023 年 9 月 18 日
@beiluo
@imyasON
OOMKilled 有什么有效的解决办法?(原因:由于容器 限制,该 pod 已终止。)
freemoon
   12
freemoon  
   2023 年 9 月 18 日
OOM 是代码问题,不是 k8s 问题( k8s 也解决不了)。检查程序哪里发生内存泄露,这个在 java 生态里面不是有很多工具能用吗
Dream95
   13
Dream95  
   2023 年 9 月 18 日
pod 内除了 Java 有没有其它进程占用了内存
G2bN4dbX9J3ncp0r
   14
G2bN4dbX9J3ncp0r  
   2023 年 9 月 18 日
@dunhanson 加内存呗
matepi
   15
matepi  
   2023 年 9 月 18 日
jvm 总体不要设过容器一半。各种 gc 相关参数打开、oom 时就能产生 heapdump ,拿出来分析内存溢出/泄露对象

还有:@imyasON

不要 不要 不要 随便随便就设置等同的 xms 和 xmx 。当堆内用量情况很平稳没有升代、长时间不需要 fullgc ,没有 fullgc 就有不能触发挂载在 finalizer 上的资源回收,可能导致包括堆外溢出等各种各样的资源耗尽问题。在确认没有堆外资源、没有 finalizer 依赖等等情况下,已经做过深度优化的基础上再考虑 xms=xmx 的设定。
chendy
   16
chendy  
   2023 年 9 月 18 日
容器内存限制 500m 的话,堆最大给 250m ,也就是堆内堆外 1:1 比较稳妥,然后上监控看看实际使用情况再酌情往大了给
Georgedoe
   17
Georgedoe  
   2023 年 9 月 18 日
java8 读的不是容器内存 , 是宿主机内存 , 容易堆溢出 , 得设置 Xms 和 Xmx
imyasON
   18
imyasON  
   2023 年 9 月 18 日
@matepi 多谢指教
julyclyde
   19
julyclyde  
   2023 年 9 月 18 日
@dunhanson 都 jdk8 了还能有多新啊

前几天有另一个帖子说过了,jdk8 不认识 cgroup 的限制,但是看/proc/meminfo 看到的又不是“给自己的”而是“整机的”资源,导致一些自动设定的容量大小参数计算错误
cctv6
   20
cctv6  
   2023 年 9 月 18 日
使用了 MaxRAMPercentage=80.0 后,容器里面的 jvm 最大堆内存是多少呢?
jdk8 现在应该还不认识 cgroup2 的资源限制的,目前应该是只能支持 v1 。如果节点上使用的是 cgroup2 的话,在使用 MaxRAMPercentage 的时候,会按照节点的内存大小来计算百分比,而不是 pod 资源限制的内存大小来计算。
notwaste
   22
notwaste  
   2023 年 9 月 18 日
看描述是 OOM Killer 的问题,容器是否有其他程序占用内存,站内搜下 OOM Killer 可能会有些收获
anubu
   23
anubu  
   2023 年 9 月 18 日
可以看看 #20 的回复。我们在 k8s 环境碰到过这个问题,JDK8 和 cgroup2 有兼容性问题,无法识别容器的 limit 导致 OOM 。可以考虑升级 JDK ,降级 cgroup ,手动指定 xmx 等方法。
julyclyde
   24
julyclyde  
   2023 年 9 月 18 日
@anubu 我觉得这个东西不能叫“有兼容性问题”;写成“未考虑与 cgroupv2 的兼容性”比较好吧
julyclyde
   25
julyclyde  
   2023 年 9 月 18 日
@anubu 我觉得这个东西不能叫“有兼容性问题”;写成“未考虑与 cgroupv2 的兼容性”比较好吧
v2nika
   26
v2nika  
   2023 年 9 月 18 日
kubectl describe pod YOUR_POD_NAME

可以看到 restart 的原因.
v2nika
   27
v2nika  
   2023 年 9 月 18 日
有一种情况是 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
   28
v2nika  
   2023 年 9 月 18 日
不过我看你的 InitialRAMPercentage 配置和 MaxRAMPercentage 配置一样, 不太可能是上面说的那个.
julyclyde
   29
julyclyde  
   2023 年 9 月 18 日
@v2nika oom 的时候,在那个 node 自己的 dmesg 里是有日志的
dunhanson
   30
dunhanson  
OP
   2023 年 9 月 18 日
@matepi 我看的一篇阿里云官方的资料上面这么推荐配置的,就我这个程序有这个问题,我看其他同事一样的配置,没啥问题 哈哈
dunhanson
   31
dunhanson  
OP
   2023 年 9 月 18 日
@Georgedoe 写了容器支持:UseContainerSupport
dunhanson
   32
dunhanson  
OP
   2023 年 9 月 18 日
@v2nika
Reason: OOMKilled
Exit Code: 137
dunhanson
   33
dunhanson  
OP
   2023 年 9 月 18 日
@cdlnls 我用 arthas 看了下,最大堆内存:5426M ,符合 75%设置,有生效
dunhanson
   34
dunhanson  
OP
   2023 年 9 月 18 日
@notwaste 只有 java 一个进程
Sezxy
   35
Sezxy  
   2023 年 9 月 18 日
我的内存最大都只设置到 70%,你 80%的话,如果 POD 内存不大,那剩余的内存不多了,可能一些堆外内存就容易占满。建议根据实际情况调整。
YzSama
   36
YzSama  
   2023 年 9 月 18 日 via iPhone
1 建议升级 11 ,2 最好的方式是容器自适应。我之前也是,后面不设最大 max 和 min 了。基本不会重启了
cheng6563
   37
cheng6563  
   2023 年 9 月 18 日
你 Java 服务没用 jni 那些 native 内存管理的话,只靠-Xmx 限制就够用了,k8s 的 pod 限制可以去掉或者设置很大。
beiluo
   38
beiluo  
   2023 年 9 月 19 日
@dunhanson #33 看了下 arthas 的截图,可以考虑把 Xmx 的 75%降到 50%左右试试,可能会增加一些 GC 频率,但是服务更稳定。一个 docker 容器里面会有 Linux 系统本身的占用+JVM 堆占用+JVM 堆外占用(包括 metaspace ,code cache ,native 等)堆占用 75%之后,其实留给其他部分的并不多了。个人理解。
cmai
   39
cmai  
   2023 年 9 月 19 日
看不到阿尔萨斯的图了,从堆外内存泄漏着手吧
notwaste
   40
notwaste  
   2023 年 9 月 19 日
https://www.v2ex.com/t/740570

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

可以看下 7 楼里面引用的答案和评论
dunhanson
   41
dunhanson  
OP
   2023 年 9 月 20 日
@beiluo 我设置 60%观察看看
dunhanson
   42
dunhanson  
OP
   2023 年 9 月 20 日
@cdlnls 是 v1 版本
dunhanson
   43
dunhanson  
OP
   2023 年 9 月 20 日
@v2nika pod 没有驱逐,只是重启了,Restarts=1
freebird1994
   44
freebird1994  
   2023 年 9 月 21 日 via Android
我也遇到了一样的问题😢
Plutooo
   45
Plutooo  
   2023 年 12 月 15 日
@notwaste 挖一下,前面的回答有些错误,不知道是不是下面这个原因

kubernetes 1.25 之后的 CRI 默认启用 cgroup v2 会导致旧版本 java 8 服务像当初 backport cgroup v1 之前的时代那样,识别不到正确的内存限制需要 Java 服务的 JDK 版本 >= 8u372 11.0.6 15+如果遇到疑似容器内存非预期暴涨,记得关注这一块,及时升级 JDK 版本
© 2026 V2EX · 59ms · 3.9.8.5