[Kubernetes] V2beta2版本HPA分析
文章目录
HPA全称是Horizontal Pod Autoscaler,是k8s集群对负载的弹性扩缩容机制,这里将介绍一下基于1.18版本的HPA过程。
 | 
 | 
在kube-controller-manager初始化了HPAController,这里主要分为两个类型的Client,RESTClient主要是基于custom metrics的client,LegacyClient则是基于Heapster metrics。
RESTClient初始化包括了resourceclient, custommetrics client, external metrics client三种类型。
 | 
 | 
事件处理
每次有HPA事件触发(Add,Update,Delete)都会将对应的hpa添加到对应的队列,然后触发a.reconcileKey执行扩缩容。如果事件不是删除则会在处理完时间之后在resync时间延迟将key重新加入队列。
reconcileAutoscaler完成hpa key操作。
- 将v1版本的autoscale转换成v2版本;
 - 通过
schema.ParseGroupVersion(hpa.Spec.ScaleTargetRef.APIVersion)解析需要扩缩容目标的GroupVersion; - 根据Group和Kind获取对应的resource mapping,然后由scale根据mapping获取集群中存在的资源,如果没有找到则会返回错误;
 - 设置Condition为
AbleToScale,将该hpa的key添加到hpacontroller的recommendation; - 如果设置了minReplicas,则配置用户的minReplicas,否则将最小副本数设置为1;
 - 如果当前副本数为0,则不进行扩缩容;当前副本大于最大副本数,则将期望副本数设置为最大副本数;当前副本小于最小副本数,则将期望副本数设置为最小副本数;否则将根据Metrics计算期望副本数;
computeReplicasForMetrics计算期望副本数,根据每个Metrics的配置进行计算,并且会将最大的副本数设置为期望副本数;computeReplicasForMetric计算每个Metrics的期望副本数,这里会根据不同的Metrics Type分别进行计算副本数,Type会分为Object,Pods,Resource,External,后面会进行分析;
 - 根据是否需要recale进行副本数的扩缩容;
 
Metrics Type
metrics的类型在v2版本中可分为四种,分别是:Object, Pods, Resource, External。HPA在计算metric对应的副本时会按照对应的类型分别进行计算。
- Object
在类型为Object的时候会根据Value的类型再进行分类,可分为Value,AverageValue两种类型进行计算, 
 | 
 | 
- Pods
Pods类型只支持AverageValue类型 
 | 
 | 
- Resource
Resource类型则支持AverageValue和AverageUtilization两种。根据用户的定义获取对应的metric, 
 | 
 | 
- External
external类型也支持两种类型AverageValue和Value。 
 | 
 | 
以上四种类型的Metrics type,和Target type之间的对应关系可以总结为下表格。
| MetricsType | AverageUtilization | AverageValue | Value | 场景 | 
|---|---|---|---|---|
| Object | No | Yes | Yes | 监控指标不是由Pod本身提供,而是由k8s集群中的其他资源提供Metrics查询,比如ingress等 | 
| Pods | No | Yes | No | CPU,memory之外的有Pod提供的自定义metrics,如用户自定义metrics | 
| Resource | Yes | Yes | No | K8s的pod的所有系统资源(包括CPU,Memory等),一般只会用于CPU,Memory和语言类相关(GC) | 
| External | NO | Yes | Yes | 来源和K8s无关的外部监控指标 | 
根据以上四种类型的Metrics Type这里针对Resource类型进行分析。在v2版本中用户可以填写多个不同的Metrics,HPA会针对每个Metrics都进行计算,然后选取副本数最大的那个进行扩缩容。
 | 
 | 
在获取resource的类型时会分为AverageValue和AverageUtilization两种。先看AverageValue类型,在GetRawResourceReplicas通过GetResourceMetric获取每个pod的所有container的对应资源的资源使用总和。然后通过calcPlainMetricReplicas计算需要副本数,包括以下工作。
- 根据selector获取所有符合条件的Pod;
 - 根据pod进行分类,如果pod处于删除或者Failed状态,则忽略;如果是Pending则加入
ignored;如果pod在上面查找的Metrics结果中没有,则加入missing;如果资源类型是CPU,还会根据pod的状态和配置的启动延迟检查和延迟初始readiness来判断pod是否加入ingored; - 将ignoredPods从Metrics结果中移除;
 - 通过GetMetricUtilizationRatio获取当前资源利用率以及当前资源利用率和目标资源利用率的比值。通过将所有的pod资源使用量相加/metrics pod数量,然后用这个值除以目标利用率得到比率Ratio;
 - rebalanceIgnored=处于pending状态的pod或者因为延迟检查的pod数量大于0 && 需要扩容;
 
- 如果没有ignore和missingPod,
- 如果Ratio-1的绝对值小于等于设定的tolerace,则返回当前副本数;
 - 如果大于tolerace,则返回Ratio*当前ReadyPod数量,还需要返回当前利用率;
 
 - 如果missing大于0;
- Ratio < 1,此时需要缩容,将missingpod的Metrics看做是100%的资源使用,即value等于targetUtilization;
 - Ratio >= 1,此时需要扩容,则将missingPod的Metrics看做0%的资源使用,即value等于0;
 
 - 如果需要扩容,并且ignoredpod>0,则将ignorepod的Metrics设置为0,
 
- 根据上面设置的Metrics重新计算Ratio,然后计算最终副本数; 每个MetricsType都会计算一次,最终取最大值。
 
behavior
上面计算之后的结果需要根据用户是否定义behavior来决定最后的操作。如果没有设定behavior,则由normalizeDesiredReplicas来判定最终的副本数,如果设置了behavior,则根据behavior具体计算副本数。
 | 
 | 
- 如果设定了behavior并downStabilizationWindow没有设定则会会将HPA的downscaleStabilisationWindow设置成缩容窗口;
 - 通过
stabilizeRecommendationWithBehaviors计算副本数;- 根据扩容还是缩容配置delaySeconds和betterRecommendation;
 - 从recommendataions获取这个hpa的最近更改情况,如果在扩缩容周期内有调整则会返回当前的副本数,如果周期内没有修改则返回真实的需要的副本数;
 - 将本次修改添加到recommedataions;
 
 
Scale
根据Metrics计算出来的副本数和当前副本数不一样则进行扩缩容操作,并更新condition和status。
 | 
 | 
总结
到此HPA的功能流程已经分析完了,其中还有一些细节可以深究,可以后续再进行分析。 v1.18以后的的HPA相比之前已经有了很大的灵活性,可以的单独控制一段时间内的扩缩容策略以此来保证服务的稳定性,但是目前还并非是GA版本,还有功能不完善,比如当前的reconcile只是单线程处理queue中的事件,如果涉及到的对象比较多的时候还是会有一些问题。目前也有一些开源项目在现有HPA的基础上进行了的扩展,比如开源项目KEDA,后面将会针对开源的keda进行分析。
文章作者 zForrest
上次更新 2021-03-10 16:37