最近使用阿里云的kubernetes容器服务,在一个应用上发现了HPA的一些奇怪的地方。如下图所示,当前使用率高于期望值使用率时,没有发生扩容事件,当当前使用率低于期望值使用率时,没有发生缩容事件。由此,通过源码分析一下其中的过程。
image.png
image.png
先大致说下HPA的原理,当一个HPA被创建时,kubernetes内部会创建一个死循环,不断的去检查当前的metrics使用率与预期的使用率做对比。当达到扩容条件时,会扩容,然后等待3分钟才会继续下一次扩容,缩容是5分钟。
现在问题来了,明显再上图中条件是达到了的,但是为什么扩容缩容都没有发生呢?
翻阅Kubernetes源码发现了一个计算副本数的函数:
https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/podautoscaler/replica_calculator.go#L64
GetResourceReplicas如下图
image.png
经过一系列的pod健康状态判断后进入这段副本数的算法
image.png
image.png
计算公式就是如官网提供的这段如下
image.png
意思是用当前使用率与预期使用率之比,再乘当前副本数,向上取整数值就是预期的新副本数
https://github.com/kubernetes/kubernetes/blob/6b388f06845009b8bd9963a8bd0796189b679486/pkg/controller/podautoscaler/metrics/utilization.go#L26
image.png
其中上图副本数运算中的usageRatio是GetResourceUtilizationRatio函数的返回值
这个函数的返回值,意思是当前使用率与预期使用率相除得出比率,从这里也可以看出,HPA的使用率计算是int32((metricsTotal * 100) / requestsTotal当前使用量与requests总量的比值,如下图
image.png
而usageRatio则是使用率除目标使用率如下图
image.png

所以说我们现在遇到的情况应道发生HPA行为,拿我们的例子来说就是math.Ceil((118/110)2),比率运算约等于2.14545454然后向上取整数值应当是3,很明显应该扩容,然后math.Ceil((92/110)3),比率运算约等于2.609090909,向上取整应该是3,缩容的情况根据我的分析,没有缩容对的,但是没有发扩容这是为什么呢?
我们提了一个阿里云工单,工单回复的算法与源码中的有出入,少了一个当前副本数的乘积运算,如下图
这笔肯定在坑人,没办法只能继续看源码。。。
image

最近又对源码翻了几翻

找到很多种判断与运算pod metrics的函数,其中一个函数GetMetricUtilizationRatio计算的是这个工作负载的每个pod资源使用的平均值如下图
image.png
在函数calcPlainMetricReplicas
image.png
它是计算deployment所有pod的平均资源使用率来套入上文中的计算公式的
image.png
image.png
也就是说是一个deployment的所有pod平均值运算来得出扩缩容具体数值的。
同时,在源码中发现了类似外推的算法来计算是否太过于接近阈值,从而判断不扩缩容
image.png
我的理解是这个方法有很多种取值运算预期节点的函数,HPA最初创建的死循环通过不停的判断这些函数来判断是否修改replicas数。

由此得出prometheus监控HPA是否达到扩容阈值判断语句如下:

CPU

image.png

内存

image.png


发热安啃
38 声望9 粉丝

FrankenFunc有梦想的6k菜鸟u