13.深入k8s:Pod 水平自动扩缩HPA及其源码分析 (5)

这里会调用groupPods将pod列表的进行一个分类统计。ignoredPods集合里面包含了pod状态为PodPending的数据;missingPods列表里面包含了在度量数据里面根据pod名找不到的数据。

因为missingPods的度量数据已经在metrics里是找不到的,然后只需要剔除掉ignored Pods集合中度量的资源就好了。

接下来调用calculatePodRequests方法统计pod中container request 设置的资源之和。

我们继续往下看:

func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUtilization int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, utilization int64, err error) { ... //获取资源使用率 usageRatio, utilization := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization) ... }

到这里会调用GetMetricUtilizationRatio方法计算资源使用率。 这个方法比较简单:

usageRatio=currentUtilization/targetUtilization;

currentUtilization = metrics值之和metricsTotal/metrics的长度;

继续往下:

func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUtilization int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, utilization int64, err error) { ... rebalanceIgnored := len(ignoredPods) > 0 && usageRatio > 1.0 if !rebalanceIgnored && len(missingPods) == 0 { if math.Abs(1.0-usageRatio) <= c.tolerance { // return the current replicas if the change would be too small return currentReplicas, utilization, nil } //如果没有unready 或 missing 的pod,那么使用 usageRatio*readyPodCount计算需要扩缩容数量 return int32(math.Ceil(usageRatio * float64(readyPodCount))), utilization, nil } if len(missingPods) > 0 { if usageRatio < 1.0 { //如果是缩容,那么将missing pod使用率设置为目标资源使用率 for podName := range missingPods { metrics[podName] = metricsclient.PodMetric{Value: targetUtilization} } } else { //如果是扩容,那么将missing pod使用率设置为0 for podName := range missingPods { metrics[podName] = metricsclient.PodMetric{Value: 0} } } } if rebalanceIgnored { // 将unready pods使用率设置为0 for podName := range ignoredPods { metrics[podName] = metricsclient.PodMetric{Value: 0} } } ... }

这里逻辑比较清晰,首先是判断如果missingPods和ignoredPods集合为空,那么检查一下是否在tolerance容忍度之内默认是0.1,如果在的话直接返回不进行扩缩容,否则返回usageRatio*readyPodCount表示需要扩缩容的容量;

如果missingPods集合不为空,那么需要判断一下是扩容还是缩容,相应调整metrics里面的值;

最后如果是扩容,还需要将ignoredPods集合的pod在metrics集合里设置为空。

接着看最后一部分:

func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUtilization int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, utilization int64, err error) { ... //重新计算资源利用率 newUsageRatio, _ := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization) if math.Abs(1.0-newUsageRatio) <= c.tolerance || (usageRatio < 1.0 && newUsageRatio > 1.0) || (usageRatio > 1.0 && newUsageRatio < 1.0) { return currentReplicas, utilization, nil } return int32(math.Ceil(newUsageRatio * float64(len(metrics)))), utilization, nil }

因为上面重新对missingPods列表和ignoredPods列表中的metrics值进行了重新设置,所以这里需要重新计算资源利用率。

如果变化在容忍度之内,或者usageRatio与newUsageRatio一个大于一个小于零表示两者伸缩方向不一致,那么直接返回。否则返回newUsageRatio* metrics的长度作为扩缩容的具体值。

介绍完了这一块我们再来看看整个逻辑流程图:

image-20201003154222404

讲完了computeReplicasForMetrics方法,下面我们继续回到reconcileAutoscaler方法中往下看。

继续往下就到了检查是否设置了Behavior,如果没有设置那么走的是normalizeDesiredReplicas方法,这个方法较为简单,我们直接看看normalizeDesiredReplicasWithBehaviors方法做了什么,以及是怎么实现的。

normalizeDesiredReplicasWithBehaviors:Behavior限制

关于Behavior具体的例子可以到这里看:

func (a *HorizontalController) normalizeDesiredReplicasWithBehaviors(hpa *autoscalingv2.HorizontalPodAutoscaler, key string, currentReplicas, prenormalizedDesiredReplicas, minReplicas int32) int32 { //如果StabilizationWindowSeconds设置为空,那么给一个默认的值,默认300s a.maybeInitScaleDownStabilizationWindow(hpa) normalizationArg := NormalizationArg{ Key: key, ScaleUpBehavior: hpa.Spec.Behavior.ScaleUp, ScaleDownBehavior: hpa.Spec.Behavior.ScaleDown, MinReplicas: minReplicas, MaxReplicas: hpa.Spec.MaxReplicas, CurrentReplicas: currentReplicas, DesiredReplicas: prenormalizedDesiredReplicas} //根据参数获取建议副本数 stabilizedRecommendation, reason, message := a.stabilizeRecommendationWithBehaviors(normalizationArg) normalizationArg.DesiredReplicas = stabilizedRecommendation ... //根据scaleDown或scaleUp指定的参数做限制 desiredReplicas, reason, message := a.convertDesiredReplicasWithBehaviorRate(normalizationArg) ... return desiredReplicas }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypgss.html