# 工作负载伸缩原理
#### HPA工作原理
HPA（Horizontal Pod Autoscaler）是用来控制Pod水平伸缩的控制器，HPA周期性检查Pod的度量数据，计算满足HPA资源所配置的目标数值所需的副本数量，进而调整目标资源（如Deployment）的replicas字段。
想要做到自动弹性伸缩，先决条件就是能感知到各种运行数据，例如Pod、容器的CPU、内存使用率等等。而这些数据的监控能力Kubernetes也没有自己实现，而是通过其他项目来扩展Kubernetes的能力，Kubernetes提供[Prometheus](https://prometheus.io/)和[Metrics Server](https://github.com/kubernetes-sigs/metrics-server)插件来实现该能力：
- [Prometheus](https://prometheus.io/)是一套开源的系统监控报警框架，能够采集丰富的Metrics（度量数据），目前已经基本是Kubernetes的标准监控方案。
- [Metrics Server](https://github.com/kubernetes-sigs/metrics-server)是Kubernetes集群范围资源使用数据的聚合器。Metrics Server从kubelet公开的Summary API中采集度量数据，能够收集包括了Pod、Node、容器、Service等主要Kubernetes核心资源的度量数据，且对外提供一套标准的API。
使用HPA（Horizontal Pod Autoscaler）配合Metrics Server可以实现基于CPU和内存的自动弹性伸缩，再配合Prometheus还可以实现自定义监控指标的自动弹性伸缩。
HPA主要流程如[图1]所示。
图1HPA流程图   
![](https://support.huaweicloud.com/usermanual-cce-autopilot/zh-cn_image_0000001712554924.png "点击放大")
**HPA的核心有如下2个部分：**
- 监控数据来源 最早社区只提供基于CPU和Mem的HPA，随着应用越来越多搬迁到K8s上以及Prometheus的发展，开发者已经不满足于CPU和Memory，开发者需要应用自身的业务指标，或者是一些接入层的监控信息，例如：Load Balancer的QPS、网站的实时在线人数等。社区经过思考之后，定义了一套标准的Metrics API，通过聚合API对外提供服务。
  - metrics.k8s.io： 主要提供Pod和Node的CPU和Memory相关的监控指标。
  
  - custom.metrics.k8s.io： 主要提供Kubernetes Object相关的自定义监控指标。
  
  - external.metrics.k8s.io：指标来源外部，与任何的Kubernetes资源的指标无关。
   
- 扩缩容决策算法 HPA controller根据当前指标和期望指标来计算缩放比例，计算公式如下：
  **desiredReplicas = ceil\[currentReplicas \* ( currentMetricValue / desiredMetricValue )\]**
  例如当前的指标值是200m，目标值是100m，那么按照公式计算期望的实例数就会翻倍。那么在实际过程中，可能会遇到实例数值反复伸缩，导致集群震荡。为了保证稳定性，HPA controller从以下几个方面进行优化：
  - 冷却时间：在1.11版本以及之前的版本，社区引入了horizontal-pod-autoscaler-downscale-stabilization-window和horizontal-pod-autoScaler-upscale-stabilization-window这两个启动参数代表缩容冷却时间和扩容冷却时间，这样保证在冷却时间内，跳过扩缩容。1.14版本之后引入延迟队列，保存一段时间内每一次检测的决策建议，然后根据当前所有有效的决策建议来进行决策，从而保证期望的副本数尽量小的发生变更，保证稳定性。
  
  - 忍受度：可以看成一个缓冲区，当实例变化范围在忍受范围之内的话，保持原有的实例数不变。 首先定义ratio = currentMetricValue / desiredMetricValue
    当\|ratio -- 1.0\| \<= tolerance时，则会忽略，跳过scale。
    当\|ratio -- 1.0\| \> tolerance时， 就会根据之前的公式计算期望值。
    当前社区版本中默认值为0.1。
    
   
HPA是基于指标阈值进行伸缩的，常见的指标主要是 CPU、内存，也可以通过自定义指标，例如QPS、连接数等进行伸缩。但是存在一个问题：基于指标的伸缩存在一定的时延，这个时延主要包含：采集时延(分钟级) + 判断时延(分钟级) + 伸缩时延(分钟级)。这个分钟级的时延，可能会导致应用CPU飚高，响应时间变慢。为了解决这个问题，CCE提供了定时策略，对于一些有周期性变化的应用，提前扩容资源，而业务低谷时，定时回收资源。
