前言
在上一篇文章中,我们介绍了在Kubernetes在处理弹性伸缩时的设计理念以及相关组件的布局,在今天这篇文章中,会为大家介绍在Kubernetes中弹性伸缩最常用的组件HPA(Horizontal Pod Autoscaler)。HPA是通过计算Pod的实际工作负载进行重新容量规划的组件,在资源池符合满足条件的前提下,HPA可以很好的实现弹性伸缩的模型。HPA到目前为止,已经演进了三个大的版本,在本文中会为大家详细解析HPA底层的原理以及在Kubernetes中弹性伸缩概念的演变历程。
HPA基本原理
HPA是根据实际工作负载水平伸缩容器数目的组件,从中可以提炼出两个非常重要的关键字:负载
和数目
。我们可以用一个非常简单的数学公式进行归纳:
下面举一个实际例子进行上述公式的阐述,假设存在一个叫A
的Deployment
,包含3个Pod
,每个副本的Request值是1核,当前3个Pod
的CPU利用率分别是60%、70%与80%,此时我们设置HPA阈值为50%,最小副本为3,最大副本为10。接下来我们将上述的数据带入公式中。
- 总的
Pod
的利用率是60%+70%+80% = 210%。 - 当前的
Target
是3。 - 算式的结果是70%,大于阈值的50%阈值,因此当前的
Target
数目过小,需要进行扩容。 - 重新设置
Target
值为5,此时算式的结果为42%低于50%,判断还需要扩容两个容器。 - 此时HPA设置
Replicas
为5,进行Pod
的水平扩容。
经过上面的推演,可以协助开发者快速理解HPA最核心的原理,不过上面的推演结果和实际情况下是有所出入的,如果开发者进行试验的话,会发现Replicas
最终的结果是6而不是5。这是由于HPA中一些细节的处理导致的,主要包含如下三个主要的方面:
- 噪声处理
通过上面的公式可以发现,
Target
的数目很大程度上会影响最终的结果,而在Kubernetes
中,无论是变更或者升级,都更倾向于使用Recreate
而不是Restart
的方式进行处理。这就导致了在Deployment
的生命周期中,可能会出现某一个时间,Target
会由于计算了Starting
或者Stopping
的的Pod
而变得很大。这就会给HPA的计算带来非常大的噪声,在HPA Controller的计算中,如果发现当前的对象存在Starting
或者Stopping
的Pod
会直接跳过当前的计算周期,等待状态都变为Running
再进行计算。 - 冷却周期
在弹性伸缩中,冷却周期是不能逃避的一个话题,很多时候我们期望快速弹出与快速回收,而另一方面,我们又不希望集群震荡,所以一个弹性伸缩活动冷却周期的具体数值是多少,一直被开发者所挑战。在HPA中,默认的扩容冷却周期是3分钟,缩容冷却周期是5分钟。
- 边界值计算
我们回到刚才的计算公式,第一次我们算出需要弹出的容器数目是5,此时扩容后整体的负载是42%,但是我们似乎忽略了一个问题,一个全新的
Pod
启动会不会自己就占用了部分资源?此外,8%的缓冲区是否就能够缓解整体的负载情况,要知道当一次弹性扩容完成后,下一次扩容要最少等待3分钟才可以继续扩容。为了解决这些问题,HPA引入了边界值△,目前在计算边界条件时,会自动加入10%的缓冲,这也是为什么在刚才的例子中最终的计算结果为6的原因。
HPA的演进历程
在了解了HPA的基本原理后,我们来聊一下HPA的演进历程,目前HPA已经支持了autoscaling/v1
、autoscaling/v1beta1
和autoscaling/v1beta2
三个大版本。大部分的开发者目前比较熟悉的是autoscaling/v1
的版本,这个版本的特点是只支持CPU一个指标的弹性伸缩,大致的yaml内容如下:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50
接下来我们再来看一下v2beta1与v2beta2的yaml,会发现里面支持的metrics类型增加了很多,结构也复杂了很多。
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
kind: AverageUtilization
averageUtilization: 50
- type: Pods
pods:
metric:
name: packets-per-second
targetAverageValue: 1k
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
target:
kind: Value
value: 10k
---
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
而这些变化的产生不得不提的是Kubernetes
社区中对监控与监控指标的认识与转变。在Kubernetes
中,有两个核心的监控组件Heapster
与Metrics Server
。Heapster是早期Kubernetes社区中唯一的监控组件,它所包含的功能很强大,通过采集kubelet提供的metrics接口,并支持监控数据的离线与归档。
大致的架构图如下,source的部分是不同的数据来源,主要是kubelet的common api与后来提供的summary api;processor的作用是将采集的数据进行处理,分别在namespace级别、cluster级别进行聚合,并创建新的聚合类型的监控数据;sink的作用是数据离线与归档,常见的归档方式包括influxdb、kafka等等。Heapster组件在相当长时间成为了Kubernetes社区中监控数据的唯一来源,也因此有非常多的和监控相关的组件通过Heapster的链路进行监控数据的消费。但是后来,Kubernetes社区发现了Heapster存在非常严重的几个问题。
- 强大繁多的Sink由不同的Maintainer进行维护,50%以上的Heapster Issues都是关于Sink无法使用的,而由于Maintainer的活跃度不同造成Heapster社区有大量的issues无法解决。
- 对于开发者而言,监控数据的类型已经不再是CPU、Memory这么简单的几个指标项了,越来越多的开发者需要应用内或者接入层的监控指标,例如ingress的QPS、应用的在线活跃人数等等。而这些指标的获取是Heapster无法实现的。
- Prometheus的成熟让Heapster的生存空间不断被挤压,自从Prometheus被CNCF收录为孵化项目,Heapster的不可替代地位被正式移除。
社区经过反思后,决定将监控的指标边界进行划分,分为Resource、Custom和External三种不同的Metrics,而Heapster(Metrics Server)的定位就只关心在了Resource这一种指标类型。为了解决代码维护性的问题,Metrics Server对Heapster进行了裁剪,裁剪后的架构如下:
去掉了Sink的机制,并将调用方式改为标准的API注册的方式,这样的好处是既精简了核心代码的逻辑又提供了替代的可能,也就是说此时Metrics Server也是可以替代的,只要实现了相同的API接口,并注册到API Server上,就可以替代Metrics Server。
接下来我们解析一下三种不同的Metrics与使用的场景
API | 注释 | |
---|---|---|
Resource | metrics.k8s.io | Pod的资源指标,计算的时要除以Pod数目再对比阈值进行判断 |
Custom | custom.metrics.k8s.io | Object: CRD等对象的监控指标,直接计算指标比对阈值<br/>Pods : 每个Pod的自定义指标,计算时要除以Pods的数目 |
External | external.metrics.k8s.io | External:集群指标的监控指标,通常由云厂商实现 |
其中autoscaling/v2beta1
支持Resource与Custom两种指标,而autoscaling/v2beta2
中增加了External的指标的支持。
最后
HPA目前已经进入了GA阶段,在大体的功能上面不会进行过多的变化,目前社区的主要发力点在如何配置化的调整细节参数、丰富监控adapter的实现等等。在本文中,我们在概念上给大家介绍了HPA的一些原理以及发展的趋势,在下一篇文章中,我们会为大家讲解如何开启v2beta1
与v2beta2
的。