Kubernetes 已成为容器编排事实上的标准,为大规模管理容器化应用程序提供了强大的平台。Kubernetes 的一项基本功能是其弹性伸缩功能,它允许应用程序根据工作负载和性能指标进行扩展或缩减。在本文中,我们将探讨 Horizontal Pod Autoscaler (HPA),它是 Kubernetes 自动缩放的关键组件。我们将深入研究 HPA 的基础知识、它的工作原理以及如何使用自定义指标和资源限制来增强其性能。
Horizontal Pod Autoscaling(简称 HPA ) 自动更新工作负载资源(例如 Deployment 或者 StatefulSet), 目的是自动扩缩工作负载以满足需求。通俗来讲是通过获取到应用的各项指标来判断应用的负载情况,根据设置的扩展策略自动化实现扩展或缩减。减少人工干预。
弹性伸缩是现代容器编排系统的一项关键功能,使应用程序能够根据需求和性能指标自动调整其资源。这种动态扩展使系统能够保持最佳性能和效率,同时最大限度地降低运营成本。在 Kubernetes 中,弹性伸缩可以在不同级别实现:
弹性伸缩的优点:弹性伸缩在维护高效且有弹性的系统方面提供了许多好处,包括:
Kubernetes 中的 Horizontal Pod Autoscaler(HPA)的基本工作机制涉及监控、伸缩策略和 Kubernetes Metrics Server。让我们分解每个组件:
HPA 持续监控 Kubernetes 集群中部署的 Pod 的指标。默认情况下,HPA 监视 CPU 利用率,但也可以配置为监视内存使用情况、自定义指标或其他每个 Pod 指标。对于每个 Pod 的资源指标(例如 CPU),HPA 从每个目标 Pod 的资源指标 API 中获取指标。根据目标利用率或原始值,控制器根据所有目标 Pod 的这些值的平均值计算缩放比例。如果某些容器缺少相关资源请求,则不会定义 CPU 利用率,并且该指标不会发生自动缩放。对于每个 Pod 自定义指标,控制器的操作类似,但使用原始值而不是利用率值。对于对象和外部指标,HPA 获取描述对象的单个指标,将其与目标值进行比较,并生成缩放比例。在autoscaling/v2 API版本中,可以将该值除以pod数量再进行比较。这些指标由 Kubernetes Metrics Server 收集和报告,该服务器聚合每个节点上运行的 kubelet 的资源使用数据。
根据上图,总结HPA基本的工作流程如下:1、HPA会持续的监控metrics server,收集pod资源的metrics 2、基于收集到的metrics,HPA计算出需要多少副本实例 3、根据计算的副本实例数量更新实例数 4、HPA对应用控制器,发起扩缩容操作,以达到需要的副本数
Pod水平自动扩缩容控制器根据当前指标和期望指标来计算扩缩比例。期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]
例如:当前度量值为200m,目前设定值为100m,那么由于200.0/100.0 == 2.0, 副本数量将会翻倍。如果当前指标为 50m,副本数量将会减半,因为50.0/100.0 == 0.5。如果计算出的扩缩比例接近 1.0 (根据--horizontal-pod-autoscaler-tolerance 参数全局配置的容忍值,默认为 0.1), 将会放弃本次扩缩。
如果 HorizontalPodAutoscaler 指定的是 targetAverageValue 或 targetAverageUtilization, 那么将会把指定 Pod 度量值的平均值做为 currentMetricValue。然而,在检查容忍度和决定最终扩缩值前,我们仍然会把那些无法获取指标的 Pod 统计进去。
所有被标记了删除时间戳(Pod 正在关闭过程中)的 Pod 和失败的 Pod 都会被忽略。如果某个 Pod 缺失度量值,它将会被搁置,只在最终确定扩缩数量时再考虑。当使用 CPU 指标来扩缩时,任何还未就绪(例如还在初始化)状态的 Pod 或 最近的指标 度量值采集于就绪状态前的 Pod,该 Pod 也会被搁置。由于受技术限制,Pod 水平扩缩控制器无法准确的知道 Pod 什么时候就绪, 也就无法决定是否暂时搁置该 Pod。
--horizontal-pod-autoscaler-initial-readiness-delay 参数(默认为 30s)用于设置 Pod 准备时间, 在此时间内的 Pod 统统被认为未就绪。
--horizontal-pod-autoscaler-cpu-initialization-period 参数(默认为5分钟) 用于设置 Pod 的初始化时间, 在此时间内的 Pod,CPU 资源度量值将不会被采纳。在排除掉被搁置的 Pod 后,扩缩比例就会根据 currentMetricValue/desiredMetricValue 计算出来。
如果缺失任何的度量值,我们会更保守地重新计算平均值, 在需要缩小时假设这些 Pod 消耗了目标值的 100%, 在需要放大时假设这些 Pod 消耗了 0% 目标值。这可以在一定程度上抑制扩缩的幅度。
此外,如果存在任何尚未就绪的 Pod,我们可以在不考虑遗漏指标或尚未就绪的 Pod 的情况下进行扩缩, 我们保守地假设尚未就绪的 Pod 消耗了期望指标的 0%,从而进一步降低了扩缩的幅度。
在扩缩方向(缩小或放大)确定后,我们会把未就绪的 Pod 和缺少指标的 Pod 考虑进来再次计算使用率。如果新的比率与扩缩方向相反,或者在容忍范围内,则跳过扩缩。否则,我们使用新的扩缩比例。
注意,平均利用率的原始值会通过 HorizontalPodAutoscaler 的状态体现( 即使使用了新的使用率,也不考虑未就绪 Pod 和 缺少指标的 Pod)。
如果创建 HorizontalPodAutoscaler 时指定了多个指标, 那么会按照每个指标分别计算扩缩副本数,取最大值进行扩缩。如果任何一个指标无法顺利地计算出扩缩副本数(比如,通过 API 获取指标时出错), 并且可获取的指标建议缩容,那么本次扩缩会被跳过。这表示,如果一个或多个指标给出的 desiredReplicas 值大于当前值,HPA 仍然能实现扩容。
最后,在 HPA 控制器执行扩缩操作之前,会记录扩缩建议信息。控制器会在操作时间窗口中考虑所有的建议信息,并从中选择得分最高的建议。这个值可通过 kube-controller-manager 服务的启动参数 --horizontal-pod-autoscaler-downscale-stabilization 进行配置, 默认值为 5 分钟。这个配置可以让系统更为平滑地进行缩容操作,从而消除短时间内指标值快速波动产生的影响。
在集群中创建Deployment和HPA
#创建Deployment
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
hpa-demo 1/1 1 0 31s
#创建HPA
$ kubectl autoscale deployment hpa-demo --cpu-percent=40 --min=1 --max=3
horizontalpodautoscaler.autoscaling/hpa-demo autoscaled
#查看HPA
$ kubectl get hpa hpa-demo -o yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-demo
namespace: default
spec:
maxReplicas: 3 #最大副本数
metrics:
- resource:
name: cpu #监控的指标的类型,这里我们监控cpu的使用率
target:
averageUtilization: 40 #监控的指标的百分比
type: Utilization
type: Resource
minReplicas: 1 #最小副本数
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hpa-demo #扩缩容的Deployment的名称,和上面的Deployment对应
我们创建了一个HPA,metrics监控的是cpu,阈值时40%,使用压测工具ab进行测试
$ ab -c 100 -n 100000 172.24.3.237:80/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 172.24.3.237 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
# 查看 pod 的 HPA的状态
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa-demo Deployment/hpa-demo 34%/40% 1 3 1 15m
hpa-demo Deployment/hpa-demo 99%/40% 1 3 1 15m
hpa-demo Deployment/hpa-demo 99%/40% 1 3 3 15m #副本数增加
hpa-demo Deployment/hpa-demo 92%/40% 1 3 3 16m
hpa-demo Deployment/hpa-demo 0%/40% 1 3 3 16m
hpa-demo Deployment/hpa-demo 0%/40% 1 3 3 21m #副本数减少
hpa-demo Deployment/hpa-demo 0%/40% 1 3 1 21m
当请求达到90000时暂停测试,观察HPA的状态,扩容至最大副本数 5min后,由于cpu利用率一直为0,副本缩容至1
在本文中,我们探讨了 Kubernetes Horizontal Pod Autoscaler (HPA) 对于有效管理应用程序的资源和可扩展性的重要性。我们讨论了依赖于 Pod 资源请求的默认 HPA 的局限性,以及使用基于资源限制的自定义指标以获得更好性能的好处。
通过设置 Prometheus 和 Prometheus Adapter,我们演示了如何为 CPU 和内存使用情况创建自定义指标,并配置 HPA 以使用这些指标来实现更精确的自动缩放。按照分步指南,您可以实施这些概念和技术来优化应用程序的资源使用并提高其整体性能。希望你能将这些技术应用到 Kubernetes 中,并体验基于自定义指标的高效、弹性自动缩放的优势!
似乎HPA已经能将解决我们很多问题了,但是仔细考虑一下,会发现以下问题:
带着上面的疑问,我们在接下来的文章中探究一下~