V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dunhanson
V2EX  ›  Kubernetes

Java k8s pod 经常重启问题

  •  
  •   dunhanson · 222 天前 · 2956 次点击
    这是一个创建于 222 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 条附言  ·  222 天前

    pod

          resources:
            limits:
              cpu: '4'
              memory: 8G
            requests:
              cpu: 50m
              memory: 500m
    
    第 2 条附言  ·  221 天前

    JDK8版本:1.8.0_345

    Reason: OOMKilled

    Exit Code: 137

    第 3 条附言  ·  221 天前

    arthas

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

    还有:@imyasON

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

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

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

    kubernetes 1.25 之后的 CRI 默认启用 cgroup v2 会导致旧版本 java 8 服务像当初 backport cgroup v1 之前的时代那样,识别不到正确的内存限制需要 Java 服务的 JDK 版本 >= 8u372 11.0.6 15+如果遇到疑似容器内存非预期暴涨,记得关注这一块,及时升级 JDK 版本
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2715 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 10:54 · PVG 18:54 · LAX 03:54 · JFK 06:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.