我在Kubernetes集群上运行了一个openjdk:8映像。我添加了内存HPA(Horizontal Pod Autoscaling),它可以很好地向上扩展,但由于JVM不会将内存从堆释放回操作系统,因此Pod不会向下扩展。
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中处理这个问题?比如,我们可以不检查操作系统的内存使用情况,而只是检查堆中的内存使用情况并据此进行缩放吗?
1条答案
按热度按时间6za6bjd01#
在Kubernetes中扩展Java应用程序有点棘手。HPA只查看系统内存,正如所指出的,JVM通常不释放已提交的堆空间(至少不会立即释放)。
有两种主要的方法可以用来解决这个问题
1.调整JVM参数,使提交的堆更接近使用的堆
根据所使用的JVM和GC,调整选项可能会略有不同,但最重要的选项是
MaxHeapFreeRatio
-已提交的堆中允许未使用的部分GCTimeRatio
-允许运行GC的频率(影响性能)AdaptiveSizePolicyWeight
-在计算新堆时如何权衡旧的和新的GC运行给出这些参数的精确值并不容易,这是快速释放内存和应用程序性能之间的折衷。最佳设置将取决于应用程序的负载特性。
帕特里克Dillon写了一篇文章,由RedHat发表,名为Scaling Java containers,深入探讨了这个主题。
2.自定义缩放逻辑
除了使用HPA,您还可以创建自己的扩展逻辑,并将其作为定期运行的作业部署到Kubernetes中,以执行以下操作:
1.检查所有单元中的堆使用情况(例如,通过在单元中运行jstat)
1.如果达到最大阈值,则横向扩展新单元
1.如果达到最小阈值,则在pod中进行缩放
这种方法的好处是可以查看实际的堆使用情况,但需要一个自定义组件。
这方面的一个示例可以在Powercloudup的文章基于Kubernetes中的CPU/内存的自动缩放-第II部分中找到