【问题标题】:Kubernetes and JVM memory settingsKubernetes 和 JVM 内存设置
【发布时间】:2021-02-01 02:27:37
【问题描述】:

在具有大量微服务的Kubernetes 集群中,其中一个专门用于运行Java 1.8 数据处理应用程序的Java Virtual Machine (JVM)。

直到最近,在该 JVM pod 中运行的作业消耗的 RAM 不到 1 GB,因此该 pod 已设置为 4 GB 的最大内存,而 JVM 没有任何明确的堆大小设置。

一些新数据现在需要大约 2.5 GB 用于整个 pod,包括 JVM(如 kubernetes top 命令所报告的,在使用增加的 8 GB 内存限制启动后),但 pod 在启动后不久就崩溃了限制为 4 GB。

使用像-Xms256m -Xmx3072m 这样的头部大小范围并限制为 4 GB 并不能解决问题。事实上,现在 pod 甚至都没有启动。

有没有什么方法可以参数化 JVM 以适应所需的 2.5 GB,而不增加 pod 的 4 GB 最大内存?

【问题讨论】:

  • 什么版本的JVM?当前版本知道查找 pod 的资源限制并相应地调整堆大小,而无需任何 -Xmx 选项。
  • Java 1.8(在问题中更新)。
  • 更具体地说? Java 8u191 特别是capable of figuring it out on its own。
  • 这个问题,它目前的措辞是没有意义的。如果一个进程占用 2.5 GB RAM,那么在具有 4 GB 内存限制的容器中运行它就没有问题。当谈到 2.5 GB 时,您是指 Java 堆大小、进程驻留集大小 (RSS) 还是虚拟内存大小 (VSZ)? This answer 可能会让您知道是什么造成了 Java 进程的内存占用。
  • Pod 的总 RAM 消耗达到 2.5 GB(更新了更多细节的问题)。基于此,4 GB 的限制应该已经足够了,但事实并非如此,并且需要通过 kubernetes top 命令将 pod 增加到 8 GB 才能运行并进行内存测量。

标签: java kubernetes memory-management jvm heap-memory


【解决方案1】:

如果您不指定 -Xmx,默认的“最大堆”是主机 RAM 的 1/4 (25%)。 JDK 10 改进了对容器的支持,因为它使用容器的 RAM 限制而不是底层主机。正如@David Maze 所指出的,这已被向后移植到 JDK 8。

假设您有足够新的 JDK 8 版本,您可以使用 -XX:MaxRAMPercentage 修改用于最大堆的总 RAM 的默认百分比。因此,您可以告诉而不是指定-Xmx,例如-XX:MaxRAMPercentage=75.0。另见https://medium.com/adorsys/usecontainersupport-to-the-rescue-e77d6cfea712

这是一个使用 alpine JDK docker 映像的示例:https://hub.docker.com/_/openjdk(请参阅“使 JVM 尊重 CPU 和 RAM 限制”一节)。

# this is running on the host with 2 GB RAM
docker run --mount type=bind,source="$(pwd)",target=/pwd -it openjdk:8

# running with MaxRAMPercentage=50 => half of the available RAM is used as "max heap"
root@c9b0b4d9e85b:/# java -XX:+PrintFlagsFinal -XX:MaxRAMPercentage=50.0 -version | grep -i maxheap
    uintx MaxHeapFreeRatio                          = 100                                 {manageable}
    uintx MaxHeapSize                              := 1044381696                          {product}
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)

# running without MaxRAMPercentage => default 25% of RAM is used
root@c9b0b4d9e85b:/# java -XX:+PrintFlagsFinal -version | grep -i maxheap
    uintx MaxHeapFreeRatio                          = 100                                 {manageable}
    uintx MaxHeapSize                              := 522190848                           {product}
openjdk version "1.8.0_265"

【讨论】:

  • 我们已经尝试了所有这些事实和配置选项,但它们都不起作用。事实上,我们正在运行比 8u200 更新的 OpenJDK 1.8 版本,但不知何故,-XX:MaxRAMPercentage 选项仍然无法识别。
  • 至少最新的 alpine JDK docker 映像似乎支持它 - 请参阅我编辑的答案以及 hub.docker.com/_/openjdk
  • 您如何检查它是否“无法识别”?您是否使用了-XX:+PrintFlagsFinal、某个监控工具,或者它只是根据您的应用程序的行为进行的猜测?
【解决方案2】:

在我的 K8s 设置中,我使用 consul 来管理 pod 配置。这是一个动态覆盖 jvm 设置的命令。这是一个非常具体的项目,但如果您使用 consul 进行配置,它可能会给您一个提示。

kubectl -n <namespace> exec -it consul-server -- bash -c "export CONSUL_HTTP_ADDR=https://localhost:8500 && /opt/../home/bin/bootstrap-config --token-file /opt/../config/etc/SecurityCertificateFramework/tokens/consul/default/management.token kv write config/processFlow/jvm/java_option_xmx -Xmx8192m"

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2018-03-07
    • 2021-10-26
    • 2021-09-10
    • 1970-01-01
    相关资源
    最近更新 更多