最近使用阿里云的kubernetes容器服务,在一个应用上发现了HPA的一些奇怪的地方。如下图所示,当前使用率高于期望值使用率时,没有发生扩容事件,当当前使用率低于期望值使用率时,没有发生缩容事件。由此,通过源码分析一下其中的过程。
先大致说下HPA的原理,当一个HPA被创建时,kubernetes内部会创建一个死循环,不断的去检查当前的metrics使用率与预期的使用率做对比。当达到扩容条件时,会扩容,然后等待3分钟才会继续下一次扩容,缩容是5分钟。
现在问题来了,明显再上图中条件是达到了的,但是为什么扩容缩容都没有发生呢?
翻阅Kubernetes源码发现了一个计算副本数的函数:
https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/podautoscaler/replica_calculator.go#L64GetResourceReplicas
如下图
经过一系列的pod健康状态判断后进入这段副本数的算法
计算公式就是如官网提供的这段如下
意思是用当前使用率与预期使用率之比,再乘当前副本数,向上取整数值就是预期的新副本数
https://github.com/kubernetes/kubernetes/blob/6b388f06845009b8bd9963a8bd0796189b679486/pkg/controller/podautoscaler/metrics/utilization.go#L26
其中上图副本数运算中的usageRatio是GetResourceUtilizationRatio
函数的返回值
这个函数的返回值,意思是当前使用率与预期使用率相除得出比率,从这里也可以看出,HPA的使用率计算是int32((metricsTotal * 100) / requestsTotal
当前使用量与requests总量的比值,如下图
而usageRatio则是使用率除目标使用率如下图
所以说我们现在遇到的情况应道发生HPA行为,拿我们的例子来说就是math.Ceil((118/110)2),比率运算约等于2.14545454然后向上取整数值应当是3,很明显应该扩容,然后math.Ceil((92/110)3),比率运算约等于2.609090909,向上取整应该是3,缩容的情况根据我的分析,没有缩容对的,但是没有发扩容这是为什么呢?
我们提了一个阿里云工单,工单回复的算法与源码中的有出入,少了一个当前副本数的乘积运算,如下图
这笔肯定在坑人,没办法只能继续看源码。。。
最近又对源码翻了几翻
找到很多种判断与运算pod metrics的函数,其中一个函数GetMetricUtilizationRatio
计算的是这个工作负载的每个pod资源使用的平均值如下图
在函数calcPlainMetricReplicas
中
它是计算deployment所有pod的平均资源使用率来套入上文中的计算公式的
也就是说是一个deployment的所有pod平均值运算来得出扩缩容具体数值的。
同时,在源码中发现了类似外推的算法来计算是否太过于接近阈值,从而判断不扩缩容
我的理解是这个方法有很多种取值运算预期节点的函数,HPA最初创建的死循环通过不停的判断这些函数来判断是否修改replicas数。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。