基于JVM Heap内存的Kubernetes HPA



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

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被设计为出于性能原因不经常从堆中释放,所以这样做不是一个好主意。有没有办法从Kubernetes处理这个问题?比如,与其检查操作系统的内存使用情况,我们能不能只检查堆中的内存使用情况,并在此基础上进行扩展?

在Kubernetes中伸缩Java应用程序有点棘手。HPA只查看系统内存,并且正如所指出的,JVM通常不会释放已提交的堆空间(至少不会立即释放)。

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

1。调优JVM参数,以便提交的堆更紧密地跟随已使用的堆

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

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

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

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

2。自定义缩放逻辑

不使用HPA,你可以创建自己的伸缩逻辑,并将其部署到Kubernetes中,作为定期运行的作业来做:

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

这种方法的好处是可以查看实际的堆使用情况,但需要自定义组件。

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

最新更新