当前位置: 首页 > 知识库问答 >
问题:

基于JVM堆内存的Kubernetes HPA

宇文航
2023-03-14

我在Kubernetes集群上运行了一个openjdk:8映像。我添加了内存HPA(水平Pod自动缩放),它可以很好地扩展,但由于JVM不会将内存从堆释放回操作系统,所以Pod不会缩小。以下是hpa。亚马尔

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: image-server
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: image-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 60

解决这个问题的一种方法是使用正确的GC并使其释放内存,但由于JVM被设计为不经常从堆中释放内存,因此这样做不是一个好主意。库伯内特斯有没有办法解决这个问题?就像不检查操作系统的内存使用情况一样,我们能不能只检查堆和扩展的内存使用情况?

共有1个答案

苏培
2023-03-14

在库伯内特斯中扩展Java应用程序有点棘手。HPA只关注系统内存,正如所指出的,JVM通常不会释放提交的堆空间(至少不会立即释放)。

有两种主要的方法可以解决这个问题

根据使用的JVM和GC,调优选项可能略有不同,但最重要的是

  • MaxHeapFreeRatio-允许未使用多少提交的堆
  • GCTimeRatio-允许GC运行的频率(影响性能)
  • AdaptiveSizePoleyWeight-计算新堆时如何权衡旧GC运行与新GC运行

给出这些值并不容易,这是快速释放内存和应用程序性能之间的折衷。最佳设置取决于应用程序的负载特性。

Patrick Dillon撰写了一篇由RedHat发布的文章,名为Scaling Java containers,深入探讨了这一主题。

不使用HPA,您可以创建自己的缩放逻辑,并将其作为定期运行的作业部署到Kubernetes中,以执行以下操作:

  1. 检查所有pod中的堆使用情况(例如,在pod中运行jstat)
  2. 如果达到最大阈值,则扩展新POD
  3. 如果达到最小阈值,则以pods为单位进行缩放

这种方法的优点是查看实际堆的使用情况,但需要一个自定义组件。

powercloudup在Kubernetes中的文章《基于CPU/内存的自动缩放-第二部分》中可以找到一个例子

 类似资料:
  • 我有这些jvm参数集

  • 我们Java开发人员有时会使用来确保我们为每个特定于线程的堆栈提供了1MB的空间。现在,我经常感到困惑,JVM从哪里借用了1MB,从堆或系统内存中借用,或者Java为线程分配任何特定的内存。你能帮我理解一下吗? 此外,我们是否有一个可视化(插件)运行时工具,可以以可理解的方式显示堆和堆栈的内容? 提前感谢。

  • 问题内容: 我们在 Tomcat 服务器上部署了一个Web应用程序。我们运行某些计划的作业,然后堆内存达到峰值并稳定下来,一切似乎都很好。但是,系统管理员抱怨内存使用率(Linux上的“ top”)随着计划的作业的增加而不断增加。堆内存和CPU内存之间有什么关联?可以通过任何JVM设置来控制它吗?我使用 JConsole 监视系统。 我通过JConsole强制进行垃圾收集,并且堆使用率下降了,但是

  • 本文向大家介绍基于jvm java内存区域的介绍,包括了基于jvm java内存区域的介绍的使用技巧和注意事项,需要的朋友参考一下 jvm虚拟机在运行时需要用到的内存区域.广泛一点就是堆和栈,其实不然,堆和栈只是相对比较笼统的说法,真正区分有如下几个 先上图一: 总的就是 java的内存模型 内存模型又分堆内存(heap)和方法区(有时也称为non-heap)和栈 堆又分新生代(Young)和老年

  • 我的问题是,如果我从java代码调用Shell脚本,脚本使用的内存,是从JVM堆空间分配,还是使用系统内存空间。

  • 问题内容: jvm进程的内存使用量一直在增加,并且从未减少。我通过在linux服务器上执行top进行检查。该应用程序正在将作业调度到群集(使用Quartz + SunJava DRMAA API) Java堆空间在应用程序生命周期内保持在限制之内,但是jvm进程显示内存使用率稳定增长且从未下降。 这是内存泄漏吗?如果是这样,为什么堆空间在限制之内。有人可以解释一下。 更新: 当我通过jconsol