HPA(Horizontal Pod Autoscaler)可以通过监控CPU使用情况(或者自定义的metrics)来自动伸缩pod的数量,被伸缩的pod需要是通过replication controller、deployment或者replica set管理。
注意:HPA不能应用于不可伸缩的对象,如:DaemonSets
HPA 被实现成一种Kubernetes API 资源和控制器。由资源来决定控制器行为。控制器周期性调整目标pod的副本数量,让目标pod的实际cpu使用率符合用户指定的数值。
HPA是怎么工作的?
HPA周期性调整目标pod数量,其调整周期由参数 --horizontal-pod-autoscaler-sync-period控制(默认值为15s)。
调整期间,控制器管理器会从默认或者自定义的metrics api查询指定的资源使用情况。
- 资源metrics(如:CPU)。控制器管理器通过metrics api为每个pod获取HPA指定的资源metrics,如果设置了目标使用值,则算出每个pod中的容器资源request与实际使用情况的百分比;如果设置的是绝对值,则计算出所有Pod平均的使用量(取决于具体的metrics类型),生成一个伸缩ratio,这个ratio用于确定伸缩多少pod。
注意:如果某些pod的容器没有需要的的资源metrics,自动伸缩将不会根据这些metrics进行伸缩。自动伸缩算法详情见:algorithm details。下面几点是将自行伸缩算法如何工作:
- 自定义metrics。控制器的功能与每个pod资源metrics类似,不同之处在于它适用原始值,而不是使用值
- 对象metrics和外部metrics。获取描述对象的单个metric,将其与目标值相比,得出一个ratio。在autoscaling/v2beta2 API版本中,可以选择在进行比较之前将该值除以pod的数量。
通常,HPA是从聚合接口获取metrics(metrics.k8s.io、custom.metrics.k8s.io以及external.metrics.k8s.io)。metrics.k8s.io通常由metrics-server提供,metrics-server需要单独部署。HPA也可以直接从Heapster中获取metrics。
注意:
FEATURE STATE: Kubernetes 1.11
从Kubernetes 1.11开始不推荐从Heapster中获取metrics
metrics API 详细介绍:Support for metrics APIs
自动缩放器会通过缩放子资源访问相关的控制器(如:replication controllers, deployments, and replica sets)。通过缩放接口动态设置pod副本数,也能检查每个pod当前的状态。缩放子资源的详细介绍
缩放算法
最基本地,HPA控制器会根据期望值和当前值的比率进行调整:
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
举个栗子,当前metric值是200m,期望值是100m,那么pod副本数将会翻一倍,因为 比率为 200.0 / 100.0 = 2.0;如果当前值是50m,50.0 / 100.0 = 0.5。如果比率接近1.0,将不会进行缩放(取决于内置的全局参数容忍度,–horizontal-pod-autoscaler-tolerance,默认值为0.1)。
如果指定了targetAverageValue 或者 targetAverageUtilization,currentMetricValue是所有目标pod的metric取均值。在检查容忍度和确定最终值之前,会结合参考pod是否就绪、是否丢失metrics。
所有已设置删除时间戳的pod(例如,pod正处于shutdown过程)以及所有失败的pod均会被忽略。
如果某个pod丢失了metrics,会有不同的计算方法。
当正在根据CPU资源缩放pod时,如果出现任何pod尚未就绪(例如:正处于初始化状态)或者其最近的metric数据是其就绪之前的数据,那么这个pod会有不同的算法
由于技术限制,HPA控制器决定是否将某些CPU metrics预留时无法精确确定一个pod首次变为就绪状态的时间。取而代之,如果pod未就绪并且在一个较短的时间内变成未就绪,HPA控制器就认为pod “尚未就绪”。这个较短的时间窗口是可配的,参数是–horizontal-pod-autoscaler-initial-readiness-delay,默认取值为30s。一旦pod变成了就绪状态,HPA认为这是pod在这个周期内的首次启动时间,周期长度亦可通过参数:–horizontal-pod-autoscaler-cpu-initialization-period设置,默认是5分钟。
此时,currentMetricValue / desiredMetricValue这个基础缩放率是用剩下的pod(去掉上述描述的暂时放一边的、放弃的pod)
如果有些pod丢失metrics,计算均值时会更保守,在缩小pod规模时会假设丢失metrics的pod使用了100%的期望资源,在扩容pod时会假设这些pod使用了0%的资源,防止pod数量失控。
此外,如果存在任何尚未就绪的pod,我们会忽略丢失指标或尚未就绪的pod,继续扩容,保守地假设尚未就绪的pod正在消耗所需指标的0% ,进一步抑制了规模扩大的程度
在考虑到pod未就绪和丢失metrics之后,会重新计算ratio。如果新的ratio与伸缩方向相反,或者在容忍度内,会跳过伸缩操作。反之,会使用新ratio进行伸缩。
注意,即使使用新的使用率,也会通过HorizontalPodAutoscaler状态报告平均利用率的原始值,而不考虑尚未准备好或丢失metrics的pod
如果在HPA中指定了多种metrics,则分别对每种metric进行计算,选择期望副本数最大的结果。
最后,在HPA执行伸缩操作前会记录伸缩数据,控制器会在一个时间窗口综合考虑所有的伸缩ratio,使用其中最大的值。时间窗口取值可通过参数配置:–horizontal-pod-autoscaler-downscale-stabilization,默认值5分钟。这也意味着缩容操作会更平滑,不会因为metric大幅波动而经常抖动。
API对象
Pod自动水平伸缩器是k8s 自动伸缩 API集合中的一个API资源,当前稳定版本可以在 autoscaling/v1 API中找到,现在只支持根据CPU自动伸缩。
beta版已经支持根据内存以及自定义metrics伸缩,接口在autoscaling/v2beta2,当工作在autoscaling/v1时,autoscaling/v2beta2中支持的新特性会当成注释(annotations)
关于API对象的更多细节见:HorizontalPodAutoscaler Object
kubectl对HPA的支持
与所有API资源一样,kubectl以标准方式支持HPA。可以使用kubectl create 命令创建一个新的自动伸缩器,使用kubectl get hpa 获取自动伸缩器列表,使用kubectl describe hpa 获取详细描述,使用kubectl delete hpa 进行删除。
额外有一个特殊的命令可用于简化HPA创建,kubectl autoscale。使用示例:kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80,执行该命令将会为foo创建一个autoscaler,目标cpu使用率设置为80%,foo的Pod数量在2-5之间。kubectl autoscale
在rolling update期间的自动伸缩
目前,k8s可以通过RC或者Deployment进行滚动升级,HPA只支持Deployment,HPA对象会与Deployment对象绑定,设置Deployment对象中Pod副本数量。
通过直接修改RC来升级时,HPA并不会生效,例如:不能讲HPA绑定RC后又对RC执行rolling update(如:使用kubectl rolling-update)。不生效的原因是滚动升级时会创建一个新RC,已完成绑定的HPA不会绑定到新RC。
冷却和延迟机制
使用HPA管理一组副本时,有可能因为metrics动态变化而导致副本数频繁波动,这种现象叫做 “颠簸”。
从1.6版本起,可以通过调整HPA全局设置来缓解这个问题,这个设置是kube-controller-manager提供的。
从1.12版本起,算法做了升级,不在需要扩容延迟机制。
- –horizontal-pod-autoscaler-downscale-stabilization:这个参数用于告诉autoscaler做完缩容操作后需要等多久才能进行下一次缩容,默认值是5分钟(5m0s)。
注意:使用者需要知道调整这个参数可能造成的影响。设置得太长,HPA对负载变化的响应也会变长;太短又会导致自动伸缩“颠簸”。
对多个metrics的支持
k8s 1.6增加了基于多metrics的伸缩容功能,可使用 autoscaling/v2beta2 指定HPA使用多个metrics。同时,HPA控制器会计算每个metric,根据每个metric 分别给出伸缩建议,使用最大的值来伸缩。
对定制metrics的支持
注意:k8s 1.2 增加了基于应用指定metrics功能的alpha版本支持,是通过使用特定的annotations实现。而k8s 1.6已经不支持这些annotations,转而使用新的伸缩容API。然而旧的收集定制metrics的方法依然存在,但是HPA不会使用这些metrics,如果之前是通过annotations指定metrics的来伸缩容的话,那么这些metrics将不好使了
k8s 1.6增加了HPA对定制metrics的支持,可以使用autoscaling/v2beta2 API给HPA增加定制metrics。k8s将会查询新的自定义指标API,以获取相应自定义指标的值。
Support for metrics APIs
对metrics API的支持
HPA控制器默认从一系列API获取metrics数据,为保证HPA能访问这些API,需要确保:
-
相关的API已经注册:
1)对于资源metrics,对应的是metrics.k8s.io API,通常由metrics-server提供,可作为集群插件启动。
2)对于定制metrics,对应的是custom.metrics.k8s.io API,由metrics方案提供者以适配器API服务器方式提供。知名的解决方案。如果想自己实现metrics方案,见:boilerplate
3)对于外部metrics,对应的是external.metrics.k8s.io API。该方案可由上面的定制metrics方案提供 -
–horizontal-pod-autoscaler-use-rest-clients 是true或者未设置,设置为false会切换到基于Heapster的自动伸缩容(不推荐)。