kubernetes - 基于 JVM 堆内存的 Kubernetes HPA
问题描述
我在 Kubernetes 集群上运行了一个 openjdk:8 映像。我添加了内存 HPA(Horizontal Pod Autoscaling),它可以很好地扩展,但由于 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 containers,深入探讨了这个主题。
2.自定义缩放逻辑
您可以创建自己的扩展逻辑并将其作为定期运行的作业部署到 Kubernetes 中,而不是使用 HPA:
- 检查所有 pod 中的堆使用情况(例如通过在 pod 内运行 jstat)
- 如果达到最大阈值,则扩展新 pod
- 如果达到最小阈值,则在 pod 中缩放
这种方法的好处是查看实际堆使用情况,但需要自定义组件。
这方面的一个例子可以在文章Autoscaling based on CPU/Memory in Kubernetes - Part II by powercloudup中找到
推荐阅读
- reactjs - 如何在玩笑测试中共享设置和拆卸?
- database - 我可以删除显示无法连接的 postgres 数据库吗?
- python - 匹配 Pandas DataFrame 时出现“KeyError: True”
- perl - 如何获取已知 Unicode 字符名称的列表
- firebase - 异步函数:未来
在颤振中布尔? - r - 循环回归和存储截距、斜率等
- python - PermissionError:[错误 13] 权限被拒绝:scr.png
- database - 如何从依赖于节点类型的 csv 在 neo4j/Cypher 中创建关系?
- pine-script - 如何检查蜡烛是否是 Pine-Script 中最大的蜡烛?
- algorithm - 查找给定 x 值的多项式序列