Kubernetes 和 JVM 内存设置
Kubernetes and JVM memory settings
在具有大量微服务的 Kubernetes
集群中,其中一个专门用于运行 Java 1.8
数据处理应用程序的 Java Virtual Machine
(JVM)。
直到最近,该 JVM pod 中的作业 运行 消耗的 RAM 不到 1 GB,因此该 pod 已设置有 4 GB 的最大内存,没有为 JVM 设置任何明确的堆大小。
一些新数据现在需要整个 pod 大约 2.5 GB,包括 JVM(如 kubernetes top
命令所报告,在启动后内存限制增加到 8 GB),但 pod 很快就会崩溃以 4 GB 的限制开始后。
使用像 -Xms256m -Xmx3072m
这样限制为 4 GB 的磁头大小范围并不能解决问题。事实上,现在 pod 甚至都没有启动。
有没有什么方法可以参数化 JVM 以容纳所需的 2.5 GB,而不增加 pod 的 4 GB 最大内存?
如果您未指定 -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"
在我的 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"
在具有大量微服务的 Kubernetes
集群中,其中一个专门用于运行 Java 1.8
数据处理应用程序的 Java Virtual Machine
(JVM)。
直到最近,该 JVM pod 中的作业 运行 消耗的 RAM 不到 1 GB,因此该 pod 已设置有 4 GB 的最大内存,没有为 JVM 设置任何明确的堆大小。
一些新数据现在需要整个 pod 大约 2.5 GB,包括 JVM(如 kubernetes top
命令所报告,在启动后内存限制增加到 8 GB),但 pod 很快就会崩溃以 4 GB 的限制开始后。
使用像 -Xms256m -Xmx3072m
这样限制为 4 GB 的磁头大小范围并不能解决问题。事实上,现在 pod 甚至都没有启动。
有没有什么方法可以参数化 JVM 以容纳所需的 2.5 GB,而不增加 pod 的 4 GB 最大内存?
如果您未指定 -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"
在我的 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"