【问题标题】:what happens if the java heap memory limits is different than the pod resource limits in kubernetes?如果 java 堆内存限制与 kubernetes 中的 pod 资源限制不同,会发生什么?
【发布时间】:2018-10-17 15:15:34
【问题描述】:

我正在使用以下配置的 pod 内运行弹簧靴。

Pod 限制:

resources:
    limits:
      cpu: "1"
      memory: 2500Mi
    requests:
      cpu: "1"
      memory: 2500Mi

命令参数:

spec:
containers:
- args:
  - -c
  - ln -sf /dev/stdout /var/log/access.log;java -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.ssl=false -Djava.security.egd=file:/dev/./urandom
    -Xms1600m -Xmx1600m -XX:NewSize=420m -XX............
  1. 如果 java 进程达到其最大堆限制(即 1600m (Xmx1600m))会发生什么
  2. 如果 Xmx 对 Pod 内的 java 进程没有影响,它可以上升到 Pod 限制权(即内存:限制部分的 2500Mi)
  3. 如果以上配置正确,那么我们就是在浪费900Mi的内存吧(2500-1600=900)

【问题讨论】:

    标签: java kubernetes heap-memory


    【解决方案1】:

    -Xmx 标志仅控制 Java 堆内存,这是运行代码时可供您自己的 Java 对象使用的空间。如果你用完了,JVM 会做垃圾回收来腾出空间。如果仍然用完,则会抛出 OutOfMemoryException。

    Java JVM 还在内部使用大量其他内存来加载类、JIT 编译等...因此,您需要在 Kubernetes 中允许更多内存,而不仅仅是 -Xmx 值。如果超过 Kubernetes 限制值,那么 Java 可能会崩溃。

    您在上面发布的配置看起来不错。通常我会在无限制运行一段时间后通过查看 Kubernetes 内存使用图来找到这些值。

    【讨论】:

    • 我看到一个 pod 的内存使用量为 1800Mi,它大于最大堆大小。这怎么可能。它应该按照您的要求抛出 OOM 错误。
    • 另外,我可以将堆限制设置为 pod 资源限制,即 -Xms2500m -Xmx2500m
    • 如前所述,JVM 使用的内存不仅仅是最大堆。额外的 ram 用于类存储、JIT 编译、JVM 本身的代码等。这被称为“非堆”内存。如果将堆限制设置为 pod 资源限制,那么最终可能会遇到 JVM 内存使用量(堆 + 非堆)处于 pod 限制并且 JVM 需要更多非堆空间的问题。在这一点上,我认为它会崩溃,但我从未测试过它。如果您对应用的堆/非堆的用途感兴趣,建议您使用 jconsole 或 visualvm 连接到应用进行监控。
    【解决方案2】:

    如果java进程已经达到了它的最大堆限制,那么如果在GC之后jvm无法重新获得堆内存,jvm就会抛出outofmemory错误。在这种情况下,Pod 将运行,但 java 进程出错。

    Xmx 对 POD 内的 jvm heap 有影响,jvm heap 不能超过这个值。在您的情况下,jvm 堆可能会增加,因为 pod 的内存相对较高。

    【讨论】:

      【解决方案3】:

      如果在 docker 中运行 JVM,而不是手动设置 -Xmx-Xms 选项,最好使用 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 来告诉 JVM 尊重容器的限制。

      请参阅https://hub.docker.com/_/openjdk/ 让 JVM 尊重 CPU 和 RAM 限制以获取更多信息。

      【讨论】:

      • 这应该与链接页面中报告的 Java 8 不再相关: > 在 Linux 容器中,OpenJDK 版本 8 及更高版本可以正确检测容器限制的 CPU 内核数量和可用 RAM。对于所有当前支持的 OpenJDK 版本,默认情况下是打开的
      猜你喜欢
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 2019-06-18
      • 1970-01-01
      • 2020-11-27
      相关资源
      最近更新 更多