使用执行器指标jvm.memory.max调整Pod大小

时间:2019-08-19 17:43:37

标签: spring-boot docker kubernetes

我正在尝试使用执行器指标信息来调整Pod的大小。使用以下K8资源配额配置;

resources:
 requests:
  memory: "512Mi"
 limits:
  memory: "512Mi"

我们观察到jvm.memory.max返回〜1455 mb。我知道此值包括堆和非堆。进一步钻入api(jvm.memory.max?tag=area:nonheap和(jvm.memory.max?tag=area:heap)分别导致〜1325mb和〜129mb。

很明显,将非堆设置为最大输出值,该值大于K8限制,那么该容器将最终被杀死。但是,为什么jvm(非堆内存)不受容器的内存配置(在K8中配置)的限制?

上面的观察对于Java 8和Java 11是有效的。下面的博客讨论了Java 8的实验性选项,其中讨论了CPU和堆配置,但未提及非堆。调整豆荚大小时有什么建议要考虑?

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap Source

1 个答案:

答案 0 :(得分:0)

Java 8具有一些标志,可以帮助运行时以更加容器感知的方式运行:

java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -jar app.jar

如果将最大容器内存限制设置为512 MB,为什么会获得129 MB的最大JVM堆内存?因此,答案是JVM中的内存消耗包括堆和非堆内存。类元数据,JIT编译代码,线程堆栈,GC和其他进程所需的内存是从非堆内存中获取的。因此,基于cgroup资源限制,JVM保留一部分内存供非堆使用,以确保系统稳定性。 非堆内存的确切数量可以有很大的不同,但是如果您正在进行资源规划,那么一个安全的选择是,堆大约占JVM总内存的80%。因此,如果将最大堆设置为1000 MB,则可以预期整个JVM大约需要1250 MB。

JVM读取到该容器限制为512M,并创建了一个最大堆大小为129MB的JVM。完全符合JDK人体工程学页面中定义的容器内存的1/4。

如果您深入研究JVM Tuning guide,将会看到以下内容。

  

除非在命令行上指定了初始堆大小和最大堆大小,否则它们是根据计算机上的内存量来计算的。默认的最大堆大小是物理内存的四分之一,而初始堆大小是物理内存的1/64。分配给年轻代的最大空间量是堆总大小的三分之一。

您可以找到有关here的更多信息。