k8s学习之-HPA


我们知道,当访问量或资源需求过高时,使用:kubectl scale命令可以实现对pod的快速伸缩功能
但是我们平时工作中我们并不能提前预知访问量有多少,资源需求多少。
这就很麻烦了,总不能为了需求总是把pod设置为最多状态,这样太浪费资源;也不能当请求量上来以后再去伸缩pod,这样会有好多请求不成功。
k8s既然是云原生时代的产品,当然得有智能,自动这些特性。
所以现在引入一个新的概念:
HPA(Horizontal Pod Autoscaler )

HPA是根据实际工作负载水平伸缩容器数目的组件,从中可以提炼出两个非常重要的关键字:负载数目。我们可以用一个非常简单的数学公式进行归纳:

bacc0483353082a419e4d86a069b906a.png

下面举一个实际例子进行上述公式的阐述,假设存在一个叫ADeployment,包含3个Pod,每个副本的Request值是1核,当前3个Pod的CPU利用率分别是60%、70%与80%,此时我们设置HPA阈值为50%,最小副本为3,最大副本为10。接下来我们将上述的数据带入公式中。

  • 总的Pod的利用率是60%+70%+80% = 210%。
  • 当前的Target是3。
  • 算式的结果是70%,大于阈值的50%阈值,因此当前的Target数目过小,需要进行扩容。
  • 重新设置Target值为5,此时算式的结果为42%低于50%,判断还需要扩容两个容器。
  • 此时HPA设置Replicas为5,进行Pod的水平扩容。

经过上面的推演,可以协助开发者快速理解HPA最核心的原理,不过上面的推演结果和实际情况下是有所出入的,如果开发者进行试验的话,会发现Replicas最终的结果是6而不是5。这是由于HPA中一些细节的处理导致的,主要包含如下三个主要的方面:

  1. 噪声处理

通过上面的公式可以发现,Target的数目很大程度上会影响最终的结果,而在Kubernetes中,无论是变更或者升级,都更倾向于使用Recreate而不是Restart的方式进行处理。这就导致了在Deployment的生命周期中,可能会出现某一个时间,Target会由于计算了Starting或者Stopping的的Pod而变得很大。这就会给HPA的计算带来非常大的噪声,在HPA Controller的计算中,如果发现当前的对象存在Starting或者StoppingPod会直接跳过当前的计算周期,等待状态都变为Running再进行计算。

  1. 冷却周期

在弹性伸缩中,冷却周期是不能逃避的一个话题,很多时候我们期望快速弹出与快速回收,而另一方面,我们又不希望集群震荡,所以一个弹性伸缩活动冷却周期的具体数值是多少,一直被开发者所挑战。在HPA中,默认的扩容冷却周期是3分钟,缩容冷却周期是5分钟。

  1. 边界值计算

我们回到刚才的计算公式,第一次我们算出需要弹出的容器数目是5,此时扩容后整体的负载是42%,但是我们似乎忽略了一个问题,一个全新的Pod启动会不会自己就占用了部分资源?此外,8%的缓冲区是否就能够缓解整体的负载情况,要知道当一次弹性扩容完成后,下一次扩容要最少等待3分钟才可以继续扩容。为了解决这些问题,HPA引入了边界值△,目前在计算边界条件时,会自动加入10%的缓冲,这也是为什么在刚才的例子中最终的计算结果为6的原因。

有了HPA,我们就不用为上面的问题而烦恼,HPA会帮我们自动完成pod的扩缩容。

当资源需求过高时,会自动创建出pod副本;当资源需求低时,会自动收缩pod副本数。
注意:首先必须确保集群中已经安装metrics-server的组件,否则无法获取集群内资源数据,无法进行以下操作。

具体这个组件不细讲了,可以看我前面文章的介绍

在 Kubernetes 中,有两个核心的监控组件 Heapster 与 Metrics Server。Heapster 是早期 Kubernetes 社区中唯一的监控组件,它所包含的功能很强大,
通过采集 kubelet 提供的 metrics 接口,并支持监控数据的离线与归档。目前已经由metrics server 取代

接下来我们解析一下三种不同的 Metrics 与使用的场景:
Resource metrics.k8s.io Pod的资源指标,计算的时要除以Pod数目再对比阈值进行判断
Custom custom.metrics.k8s.io Object: CRD等对象的监控指标,直接计算指标比对阈值
Pods 每个Pod的自定义指标,计算时要除以Pods的数目
External external.metrics.k8s.io External:集群指标的监控指标,通常由云厂商实现

                                                  

 

 

 

 


原理:
通过集群内的资源监控系统(metrics-server),来获取集群中资源的使用状态。
根据CPU、内存、以及用户自定义的资源指标数据的使用量或连接数为参考依据,来制定一个临界点,一旦超出这个点,HPA就会自动创建出pod副本,如下图

 

 

 

HPA通过定期(定期轮询的时间通过–horizontal-pod-autoscaler-sync-period选项来设置,默认的时间为30秒)通过Status.PodSelector来查询pods的状态,获得pod的CPU使用率。然后,通过现有pods的CPU使用率的平均值(计算方式是最近的pod使用量(最近一分钟的平均值,从metrics-serve中获得)

除以设定的每个Pod的CPU使用率限额)跟目标使用率进行比较,并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。

计算扩容后Pod的个数:sum(最近一分钟内某个Pod的CPU使用率/量的平均值)/CPU使用上限的整数+1

流程
1、创建HPA资源,设定目标CPU使用率限额,以及最大、最小实例数
2、收集一组中(PodSelector)每个Pod最近一分钟内的CPU使用率,并计算平均值
3、读取HPA中设定的CPU使用限额
4、计算:平均值之和/限额,求出目标调整的实例个数
5、目标调整的实例数不能超过1中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩容至最大的实例个数
6、回到2,不断循环

HPA的演进历程

在了解了HPA的基本原理后,我们来聊一下HPA的演进历程,目前HPA已经支持了三个大版本

通过kubectl api-versions可以看到

autoscaling/v1 #只支持通过cpu为参考依据,来改变pod副本数
autoscaling/v2beta1 #支持通过cpu、内存、连接数以及用户自定义的资源指标数据为参考依据。
autoscaling/v2beta2 #同上,小的变动

kubectl explain hpa ##默认查询到的是autoscaling/v1版本
kubectl explain hpa --api-version=autoscaling/v2beta1 ##如果使用其他版本,可以使用--api-version指明版本

目前比较熟悉的是autoscaling/v1 的版本,这个版本的特点是只支持 CPU 一个指标的弹性伸缩
我们可以简单的通过 kubectl autoscale 命令来创建一个 HPA 资源对象
Controller默认30s轮询一次(可通过 kube-controller-manager 的--horizontal-pod-autoscaler-sync-period 参数进行设置),
查询指定的资源中的 Pod 资源使用率,并且与创建时设定的值和指标做对比,从而实现自动伸缩的功能
kubectl autoscale deployment hpa-demo --cpu-percent=10 --min=1 --max=10
或者用yaml 文件

 

 

注意一下如果要想让 HPA 生效,对应的 Pod 资源必须添加 requests 资源声明

 

 

 kubectl describe hpa hpa-demo

 

 

现在可以看到 HPA 资源对象已经正常了,现在我们来增大负载进行测试,我们来创建一个 busybox 的 Pod,并且循环访问上面创建的 Pod

$ kubectl run -it --image busybox test-hpa --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://10.244.4.97; done

$ kubectl get hpa

我们可以看到已经自动拉起了很多新的 Pod,最后定格在了我们上面设置的 10 个 Pod,同时查看资源 hpa-demo 的副本数量,副本数量已经从原来的1变成了10个

$ kubectl get pods -l app=nginx --watch

 

 

 kubectl get deployment hpa-demo

 

 

 同样的这个时候我们来关掉 busybox 来减少负载,然后等待一段时间观察下 HPA 和 Deployment 对象

 

基于内存和自定义指标

这里会用到两个版本autoscaling/v1beta1 和 autoscaling/v1beta2

 

这两的测试方式也可以通过上面的流程测试一下

除了基于 CPU 和内存来进行自动扩缩容之外,我们还可以根据自定义的监控指标来进行。这个我们就需要使用 Prometheus Adapter,Prometheus 用于监控应用的负载和集群本身的各种指标,Prometheus Adapter 可以帮我们使用 Prometheus 收集的指标并使用它们来制定扩展策略,这些指标都是通过 APIServer 暴露的,而且 HPA 资源对象也可以很轻易的直接使用。

这块内容相关的可以参考我之前的文章

https://www.cnblogs.com/centos-python/articles/10921991.html

推荐一篇博文

https://github.com/stefanprodan/k8s-prom-hpa

https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

这里在强调说明一下,因为我这边生成环境POD 是有两个容器,分别是nginx 和  php,如果只对单个容器做资源声明,HPA 的cpu资源不显示,需要对两个容器都做资源声明

 

后续可以加监控监控这种HPA 的扩展

 

 这是我们线上报警的规则,当然监控的项目比较多,自己根据实际情况去监控,可以去prometheus 看相应的监控指标

 

我们现在回过头来看看 metrics-server 创建的对象PodMetrics:

$ kubectl get podmetrics -n demo
NAME AGE
nginx-deployment-6d4b885966-zngnd 0s
nginx-deployment-6d4b885966-lgwd9 0s
nginx-deployment-6d4b885966-hhk7v 0s
$ kubectl get podmetrics -n demo nginx-deployment-6d4b885966-zngnd -o yaml
apiVersion: metrics.k8s.io/v1beta1
containers:
- name: nginx
usage:
cpu: "0"
memory: 5524Ki
kind: PodMetrics
metadata:
creationTimestamp: "2020-10-13T09:38:15Z"
name: nginx-deployment-6d4b885966-zngnd
namespace: demo
selfLink: /apis/metrics.k8s.io/v1beta1/namespaces/demo/pods/nginx-deployment-6d4b885966-zngnd
timestamp: "2020-10-13T09:37:55Z"

HPAController 就是通过这些 PodMetrics 来计算平均的 CPU 使用率,从而确定 spec.replicas 的新数值。

 

常见的问题汇总

https://help.aliyun.com/knowledge_detail/186980.html

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM