我们应该在Kubernetes容器中设置-Xmx(最大Java堆大小)吗?

8

简述;

在 Kubernetes 应用中为什么要设置 -Xmx-Xms?


我们接手了一个 Kubernetes 应用程序,出现了内存不足的错误。看起来最初的开发人员设置了 Kubernetes 资源限制(0.95 CPU 核心和 4GB 内存),如下所示。然而,他们还在 JAVA_OPTS -Xmx 中设置了最大堆大小为 800MB。

enter image description here

我找到了很多关于-Xmx的最佳设置的好资料(例如this one),但是找不到以下问题的直接答案:我们是否真的需要在kubernetes容器中设置-Xmx(以及次要的-Xms)?我们已经在容器的resources上设置了硬限制,那么设置这些标志的意义是什么?如果完全删除它们,后果会是什么?应用程序是否会更频繁地进行GC?它是否会动态扩展堆大小,还是堆大小将固定在某个默认最大值(如256MB)?在比例上设置-Xmx有什么经验法则吗?

就我个人而言,在我们的代码中删除了所有这些内容,并在相对较新的 k8s 版本上运行(截至撰写本文,我认为是 1.21 或 1.22),我不必考虑这些标志。 - Adam Hughes
2个回答

4
如果您未设置最大堆大小,则行为取决于所使用的Java版本。当前的JRE支持确定容器限制并使用其指导内部启发式算法。
在旧版本中运行时,用于堆的内存将基于容器可见的物理内存来确定,这可能过多。
请注意,达到容器的内存限制将导致杀死进程并重新启动容器。
我建议您使用经过操作测试确定的合理值作为Xmx和Xms,以获得稳定的内存使用情况。

6
(注意,“当前JRE”包括两年前的旧版本JRE,例如OpenJDK 8;如果您的基础架构经常更新,则应具有根据资源限制自动确定堆大小的支持。) - David Maze
好的,谢谢!我会检查我们在云端使用的当前JDK。 - Adam Hughes

-1

完全不同意:在容器环境中拥有动态堆大小有什么意义呢?内存已经受到限制。在我看来,你应该始终为容器设置和使用相等的XMS和XMX值,因为JVM调整堆内存大小对你没有任何好处。 - undefined
不,它不是动态的。这样你就不需要两次指定内存限制,一次是给容器,一次是给Java应用程序。否则,有人可能会不断增加容器内存,并想知道为什么它对他的应用程序没有帮助。 如果你想使用一个更大的Pod,并且还需要在一些完全不同的地方调整这个参数,那么这将非常麻烦。 - undefined
你可能没有理解这个概念。 - undefined
嗯,现在我明白你为什么这样说了。当你说“有人可以不断增加容器内存,却不明白为什么对他的应用没有帮助”时,依我之见(再次强调),这是一个典型的例子,说明该服务并不适合在容器环境中运行。对我来说,所有的服务都必须以可预测的资源管理方式部署和运行:如果你需要处理增加的负载,应该启动新的(无状态)实例,而不是增加容器内存的使用量。问问任何SRE工程师,他们是否会批准一个需要监控和根据需求增加内存分配的应用程序。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接