【发布时间】:2019-03-06 20:59:21
【问题描述】:
我正在运行包含 JVM (java8u31) 的 Docker 容器。这些容器被部署为 Kubernetes 集群中的 pod。通常我会为 Pod 获得 OOM,然后 Kubernetes 会杀死 Pod 并重新启动它。由于我是 Kubernetes 新手,因此在寻找这些 OOM 的根本原因时遇到了问题。
-
这里是JVM参数
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xms700M -Xmx1000M -XX:MaxRAM=1536M -XX:MaxMetaspaceSize=250M -
这些容器被部署为有状态集,以下是资源分配
resources: requests: memory: "1.5G" cpu: 1 limits: memory: "1.5G" cpu: 1所以分配给容器的总内存与 MaxRam 匹配
-
如果我使用
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/etc/opt/jmx/java_pid%p.hprof,这将无济于事,因为一旦出现 OOM,pod 就会被杀死并重新创建并启动,因此 pod 中的所有内容都会丢失获取线程或 HEAP 转储的唯一方法是通过 SSH 连接到 pod,我也无法使用,因为 pod 是在 OOM 之后重新创建的,所以在 OOM 时我没有得到内存占用。我在 OOM 之后 SSH,这并没有多大帮助。
-
我还使用 visualVM、jHat 分析了代码,但找不到大量内存占用,这可能导致 JVM 中运行的线程消耗过多内存或可能存在泄漏。
感谢任何帮助解决 Kubernetes 引发的 OOM。
【问题讨论】:
-
你设置了
-XX:+UseCGroupMemoryLimitForHeap和-Xms和-XX:MaxRAM=1536M。你明白他们的意思吗?他们是怎么做到的interact -
关于你的
-XX:+HeapDumpOnOutOfMemoryError问题,在你到达堆转储之前容器重启 - 如果JVM实际上已经OOM,那么你需要在主机节点上安装一个卷并将转储写入该路径。看这里kubernetes.io/docs/tasks/configure-pod-container/… -
感谢 @Eugene 指出 JVM 参数。现在我明白 Xmx 会覆盖 Cgrouplimits。我还在本地进行了一些测试,发现提供 MaxRamFraction 和 MaxRAM 是必不可少的,例如docker run -m 1GB openjdk:8u131 java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XX:MaxRAM=700M -XX:MaxMetaspaceSize=200M -XshowSettings:vm -version VM 设置:最大。堆大小(估计):622.50M 人体工程学机器类:服务器使用 VM:OpenJDK 64 位服务器 VM。现在,我需要再做一些测试来指定 -XX:MaxMetaspaceSize
-
感谢 @nickebbitt 在转储到已安装卷时指出 k8 链接。
标签: docker java-8 kubernetes jvm