HPA似乎很简单。我通过遵循所有的文档来启用它。但它对我不起作用!
这是真的,HPA(水平Pod自动定标器)不工作的某些应用或者是应用程序所有者做了什么错误的事情,破坏了HPA?继续往下读吧。
在继续讨论这些问题之前,让我们简要了解一下通常如何为应用程序配置HPA。
作为一个例子,让我们考虑一个服务busybox-1
。目标是让这个服务在CPU使用率超过80%时自动伸缩。
由于目前Pod垂直伸缩受到各种硬件资源的限制,我们使用HPA实现自动定标。
下面是HPA资源的示例清单。
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: busybox-1
spec:
scaleTargetRef:
kind: Deployment
name: busybox-1
minReplicas: 3
maxReplicas: 4
targetCPUUtilizationPercentage: 80
注意:虽然本文将以基于CPU利用率的水平Pod自动伸缩为例,但这些概念同样适用于任何可用于自动伸缩的指标。
使用此HPA资源配置busybox-1
部署非常简单,只需运行以下命令。
$ kubectl create -f hpa.yaml
horizontalpodautoscaler.autoscaling/busybox-1 created
如下图所示,可以查看HPA资源的当前状态。
$ kubectl get hpa
NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE
busybox-1 Deployment/busybox 0% / 80% 3 4 1 11m
当所有pod的平均CPU使用率超过80% (targetcpuutilationpercentage)时,HPA将启动其他pod。以下所示计算了额外需要Pod的数量。
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
在任何时间点应该运行的最小副本数量由minReplicas参数控制,HPA可将部署扩展到的最大副本数量,这由HPA清单中的maxReplicas参数控制。
我敢肯定,所有这些看起来都很简单,以至于你现在想知道HPA可能出了什么问题而无法工作。好吧,继续读下去!
下图考虑了具有稳定工作负载的服务示例。图中有三幅图。从上到下排列,它们描述如下:
100%为1个pod的容量
服务被配置为随HPA自动伸缩。从上图的右上角可以看到,它被配置为以80%的期望CPU使用率运行,minReplicas参数设置为1。
记住这些要点之后,让我们看看在上面的例子中随着时间的推移发生了什么。
让我们关注图中我们还没有描述的一些东西——蓝色的垂直线和橙色的垂直线。
在检测和缩放之间有一个时间延迟
从图中可以看出,这两者之间存在时间差(即,在超出目标CPU使用率阈值和额外副本启动并运行之间存在时间差。
延迟的原因将在本文后面描述
自动缩放延迟=从超出目标CPU使用率阈值到额外副本启动并运行之间的时间间隔
现在让我们关注红色虚线。这是一个标记,表示如果服务没有扩展,pod将达到100% CPU利用率的时间。我们假设您不希望pod的CPU使用率达到这个级别,因为您在这个级别上观察到大量的节流—这会导致严重的降级和故障。
autoscale可用的最大时间=超出目标CPU利用率阈值和pod达到100% CPU利用率之间的时间滞后.
为了使自动缩放解决方案有效,一个关键的要求是让自动缩放延迟<自动缩放可用的最大时间
减少自动扩展延迟超过最大可用时间的风险的一种方法是减少targetcpuutilationpercentage参数的值。
例如,在上面的场景中,如果targetcpuutilationpercentage设置为40%(而不是80%),那么阈值将会提前突破,并且需要3倍的时间才能达到100%的CPU利用率。因此,这种方法大大降低了降级/失效的风险。
但是,这里有一个权衡:目标CPU利用率越低,处理相同工作负载所需的pod数量就越多(在上面的示例中为240%)。下表说明了这种权衡和相关成本。
降低用于扩展的目标CPU利用率可以提供响应更快的服务,但成本也更高
处理40%目标CPU利用率的给定工作负载所需的pod数量是处理80%目标CPU利用率的相同工作负载所需的pod数量的两倍。
正如本节所解释的,目标利用率的选择在开始时可能看起来很简单,但应用程序所有者在对这个关键参数做出决策时,最好注意涉及的权衡。
更高的目标CPU利用率=更高的降级/故障风险 较低的目标CPU利用率=更昂贵的硬件资源
现在,让我们考虑一个具有尖峰工作负载的服务示例。下图包含2个图表。从上到下排列,它们描述如下:
服务被配置为随HPA自动伸缩。从上图的右上角可以看到,它被配置为以80%的期望CPU使用率运行,minReplicas参数设置为1。
记住这些要点之后,让我们看看这个例子中随着时间的推移会发生什么。
HPA有时无法检测工作负载峰值
为了理解这种行为的根本原因,让我们看一下下面演示的示例Kubernetes集群。
下面解释了上述插图中的各种步骤。
让我们来看看一些峰值的例子,以及在这些峰值期间HPA观察到了什么。
上面的示例显示了一个服务的3个pod在30秒内的CPU使用情况(metrics-server解析)。其中一个pod在T+1时出现CPU峰值,将该pod的CPU使用率推高至90%。这是在HPA中配置的> 80% targetAverageCPUUtilization参数。然而,在这个工作负载高峰期间,HPA不会向pod扩展,因为:
由于这些原因,即使在一个pod中出现了工作负载峰值,导致该pod上的> CPU使用量达到80%,HPA也不会通过扩展更多副本来做出响应。
在本例中,所有pod在T+1时经历了CPU峰值>80%。然而,在30秒的时间内,CPU平均使用量的总和只有22%——再次远低于80%的目标。因此,HPA不会通过扩展更多的副本来响应。
在本例中,工作负载峰值持续的时间更长,约为5秒。然而,平均CPU利用率聚合超过30秒= 31% < 80% targetaveragecpu利用率。因此,HPA同样不能向外扩展部署。
最后,在本例中,所有pod的平均CPU使用率在30秒(~ 26秒)的大部分时间内始终高于targetAverageCPUUtilization值。这将导致总平均CPU使用率= 81% > 80% targetaveragecpu利用率。因此,HPA通过添加额外的副本来扩展部署。
总结无损检测的主要发现。
HPA可能不是检测短暂/短期内产生工作负载峰值的最佳解决方案
在这种工作负载下实现HPA规模的可能解决方案包括:
注意:指标的分辨率越高,集群上的开销就越大。因此,在无损检测和集群开销/可靠性之间需要进行权衡。
权衡:无损检测vs集群开销/可靠性
注意:Burstable QoS不保证可伸缩性(即)更多的资源分配给pod,只有在可用的情况下。如果调度pod的节点100%繁忙,则pod无法获得额外资源。此外,与有保证QoS的pod相比,在资源压力情况下,具有突发QoS的pod更有可能(并非总是)被驱逐。因此,这里的权衡是无损检测和可伸缩性保证+可用性之间的权衡。
权衡:无损检测vs可伸缩性保证+可用性
让我们考虑一下在本文的目标利用率一节中前面描述的稳定工作负载的例子。
在该部分中,我们讨论了检测(蓝色虚线)和缩放(橙色虚线)之间的时间延迟,以及如何通过调整targetAverageCPUUtilization参数来管理这种延迟(尽管有一定的成本)。
这一节中,我们将深入研究这种延迟的根本原因,并探讨减少这种延迟的可能方法。
如上所示,主要的贡献者与HPA的自动缩放延迟是:
下面是本文前面讨论的Kubernetes集群示例。
正如前面所讨论的:
在本例中,根据HPA轮询的时间,可能会有30 - 45秒的延迟(30秒度量服务器解析+ 15秒HPA轮询频率)。
这是导致自动缩放延迟的原因之一。
另一个可能是更重要的自动缩放延迟的组成部分是应用程序启动。在高水平上,用HPA自动缩放将经过3个步骤
虽然这个过程的第3步——容器准备就绪——不是由HPA负责的,但它是自动缩放产生任何影响的关键。如果一个新的副本不能从流量中分得一杯羹,那么扩展它还有什么意义呢?
当HPA发出一个scale请求时,Kubernetes控制平面将新的pod调度到一个适当的工作节点上运行。但是,在调度程序调度pod和pod实际开始使用流量之间有一个时间差。这种延迟是由以下原因引起的:
帮助autoscaler更快的可能解决方案:
权衡:启动性能vs运行时性能
权衡:响应性vs集群开销和可靠性
HPA对于处理存在波动的应用程序无疑是有用的。但是,有时,在试图管理它们的容量时,HPA可以自动扩展应用程序,以至于一个应用程序可以占用Kubernetes集群中的所有资源,而留给在集群上运行的其他应用程序的资源非常少---如下图所示,其中应用程序1占用了所有资源。
您可能想知道——应用程序能够根据工作负载进行伸缩,这不是一件好事吗?如果集群的资源压力过大,可以不使用集群自动扩展器来处理这个问题吗?!
无限制的扩展可能会损害集群中应用程序的性能/可靠性
这确实有些道理,而且肯定是一个可行的解决方案。但想象一下,如果其中一个应用程序受到机器人流量的狂轰轰炸,其工作负载将是正常工作负载的100倍。在这种情况下,HPA可能会将应用程序扩展100倍。这有以下副作用:
消除这种情况的一种方法是将HPA限制为最大的副本数量,防止无限制的缩放。您可以使用HPA清单中的maxReplicas参数对此进行配置。
在下面的示例清单中,HPA被限制为最多4个副本。
对于大多数应用程序,工作负载是可预测的。因此,为maxReplicas参数提供一个值并不太难。但是,当工作量无法预测时,你该怎么办?
例如,假设你经营一个新闻网站。对新闻的需求会随着新闻的趋势而上下波动。如何预测系统上的最大预期负载?!
准确预测最大预期工作量可能是不可能的。但是,一个基于事实的、合理的近似估计要比一个随机的估计好得多。例如:在新闻网站示例中,您可以使用以下指标得出一个估计。
下图显示了30天内的这些指标。
从这里可以看出,30天内使用的Pod最多是7个。因此,当选择maxReplicas参数时,明智的做法是添加一个缓冲区,但要确保这是合理的(即),在这种情况下,将maxReplicas参数设置为10比将其设置为100更好。
这里的权衡是弹性和无限扩展。在上面的例子中,如果有一条突发新闻完全抛弃了任何过去的数字,导致100倍的正常工作负载,HPA将无法处理这一情况。
权衡:弹性vs无限扩展