# 节点伸缩原理
HPA是针对Pod级别的，可以根据负载指标动态调整副本数量，但是如果集群的资源不足，新的副本无法运行的情况下，就只能对集群进行扩容。
[CCE集群弹性引擎](https://support.huaweicloud.com/usermanual-cce/cce_10_0154.html)是Kubernetes提供的集群节点弹性伸缩组件，根据Pod调度状态及资源使用情况对集群的节点进行自动扩容缩容，同时支持多可用区、多实例规格、指标触发和周期触发等多种伸缩模式，满足不同的节点伸缩场景。
#### 前提条件
使用节点伸缩功能前，需要安装[CCE集群弹性引擎](https://support.huaweicloud.com/usermanual-cce/cce_10_0154.html)插件，插件版本要求1.13.8及以上。
#### Cluster Autoscaler工作原理
[Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)主要流程包括两部分：
- 扩容流程： Autoscaler会每隔10s检查一次所有未调度的Pod，根据用户设置的策略，选择出一个符合要求的节点池进行扩容。
  ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
  - Autoscaler检测未调度Pod进行扩容时，使用的是与Kubernetes社区版本一致的调度算法进行模拟调度计算，若应用调度采用非内置kube-scheduler调度器或其他非Kubernetes社区调度策略，此类应用使用Autoscaler扩容时可能因调度算法不一致出现无法扩容或多扩风险。
  
  - 如果集群中同时存在多种不同规格的未调度Pod，Autoscaler扩容时可能因资源碎片原因导致过度扩容，具体表现为Autoscaler会先触发一次节点扩容，但在节点创建的过程中再次触发扩容。
    这是由于Autoscaler扩容计算时的算法与调度器的实际行为存在差异：
    - **首次扩容**：在首次扩容时，Autoscaler采用贪心的策略，计算出的节点数是理论上的"最小值"。
    
    - **节点创建中**：当首次扩容触发后，节点还处于创建过程中时，当前的Pod仍旧处于无法调度状态。
    
    - **再次计算**：Autoscaler的扩容计算是不停循环进行的，Autoscaler会先将首次扩容时增加的"创建中节点"纳入考量，尝试通过集成的调度器框架将未调度Pod模拟调度到这部分节点上。
    
    - **产生资源碎片进一步扩容**：但调度器框架会综合考量资源利用率等因素选择Pod调度的节点，该过程可能会产生资源碎片，导致首次扩容增加的节点无法满足同一批Pod的调度，从而需要进行额外扩容。
      
    
- 缩容流程：Autoscaler每隔10s会扫描一次所有的Node，如果该Node上所有的Pod Requests少于用户定义的缩容百分比时，Autoscaler会模拟将该节点上的Pod是否能迁移到其他节点。
  当集群节点CPU与内存预分配量均小于缩容阈值且持续一段时间时（默认10min），会触发集群缩容操作（即节点会被自动删除）。当节点存在以下几种状态的Pod时，不可缩容：
  - Pod有设置Pod Disruption Budget（即[干扰预算](https://kubernetes.io/zh/docs/tasks/run-application/configure-pdb/)），当移除Pod不满足对应条件时，节点不会缩容。
  
  - Pod由于一些限制，如亲和、反亲和等，无法调度到其他节点，节点不会缩容。
  
  - Pod拥有cluster-autoscaler.kubernetes.io/safe-to-evict: 'false'这个annotations时，节点不会缩容。
  
  - 节点上存在kube-system命名空间下的Pod（除kube-system命名空间下由DaemonSet创建的Pod），节点不会缩容。
  
  - 节点上如果有非controller（即Deployment/ReplicaSet/Job/StatefulSet等工作负载）创建的Pod，节点不会缩容。
  
  
  ![](https://support.huaweicloud.com/usermanual-cce/public_sys-resources/note_3.0-zh-cn.png)
  - 当节点符合缩容条件时，Autoscaler将预先给节点打上DeletionCandidateOfClusterAutoscaler污点，限制Pod调度到该节点上。当Autoscaler插件被卸载后，如果节点上依然存在该污点请您手动进行删除。
  
  - 对于非完全空闲节点，为了确保系统的稳定性和资源的高效利用，Autoscaler采用保守策略逐个节点进行缩容。如果Pod设置优雅退出，可能导致非空闲节点排水时间较长，缩容时间较长。
    
 
#### Cluster AutoScaler架构
Cluster AutoScaler架构如[图1]所示，主要由以下几个核心模块组成：
图1Cluster AutoScaler架构图   
![](https://support.huaweicloud.com/usermanual-cce/zh-cn_image_0000001904520973.png "点击放大")
**说明如下：**
- Estimator： 负责扩容场景下，评估满足当前不可调度Pod时，每个节点池需要扩容的节点数量。
- Simulator： 负责缩容场景下，找到满足缩容条件的节点。
- Expander： 负责在扩容场景下，根据用户设置的不同的策略，从Estimator选出的节点池中，选出一个最佳的选择。当前Expander有多种策略，如[表1]。
   表1**CCE支持的Expander策略** 
  | 策略              | 策略说明                                                                                                                                                                                                                                                                                                                                                | 使用场景                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | 模拟样例                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
  |:---|:---|:---|:---|
  | Random         | 随机选择一个可调度节点池中执行本次扩容。                                                                                                                                                                                                                                                                                                                               | 此策略通常作为其他更复杂策略的基础退避策略。仅当其他优选策略无法决策时，作为备选策略使用，通常不建议直接配置使用。                                                                                                                                                                                                                                                                                                                                                                                                             | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，评估节点池1和节点池2中扩容的节点均可调度。  3. autoscaler决策优选节点池，将在节点池1和节点池2范围中随机选择一个节点池执行扩容。                                                                           |
  | most-pods        | 组合型策略，优先级排序为：most-pods \> random。 优先选择扩容后能调度最多Pods的节点池。如果存在多个节点池满足条件，则基于random策略进一步决策。                                                                                                                                                                                                                                  | 此策略基于最多可调度Pods数量作为优选依据。                                                                                                                                                                                                                                                                                                                                                                                                                                              | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，评估节点池1和节点池2中扩容的节点均可调度部分Pending Pods。  3. autoscaler决策优选节点池，评估节点池1扩容后可调度工作负载新增的20个Pods，而节点池2扩容仅可调度工作负载新增的10个Pods，因此优选节点池1执行本次扩容。            |
  | least-waste       | 组合型策略，优先级排序为：least-waste \> random。 评估本次扩容的节点池整体CPU及内存资源分配率，优先选择具有最小浪费的CPU及内存资源的节点池。如果存在多个节点池满足条件，则基于random策略进一步决策。                                                                                                                                                                                                      | 此策略将CPU及内存资源最小浪费分数作为优选依据。 其中最小浪费分数wastedScore定义公式如下： - wastedCPU = (待扩容节点的CPU总量 - 待调度Pods的CPU总量) / 待扩容节点的CPU总量  - wastedMemory = (待扩容节点的内存总量 - 待调度Pods的内存总量) / 待扩容节点的内存总量  - wastedScore = wastedCPU + wastedMemory   | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，评估节点池1和节点池2中扩容的节点均可调度部分Pending Pods。  3. autoscaler决策优选节点池，评估节点池1扩容后最小浪费分数小于节点池2，因此优选节点池1执行本次扩容。                                                |
  | priority       | 组合策略，优先级排序为：priority \> least-waste \> topology-balance \> random。 基于节点池/伸缩组优先级配置增强的least-waste策略。如果存在多个节点池满足条件，则基于least-waste策略进一步决策。 在least-waste策略的基础上，topology-balance策略可基于不同可用区均衡节点数量，即优先选择节点数量少的AZ进行扩容，尽可能保证各个AZ间的节点数量均衡。该策略在1.23.122、1.25.117、1.27.85、1.28.52、1.29.14及以上版本的插件中可用。 | priority可通过Console/API主动配置节点池/伸缩组优先级，least-waste则在通用场景下降低资源浪费比例。在此基础上，topology-balance策略可以尽可能保证各个AZ间的节点数量均衡。此策略通用性较好，当前作为**默认优选策略**。                                                                                                                                                                                                                                                                                                                                   | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，评估节点池1和节点池2中扩容的节点均可调度部分Pending Pods。  3. autoscaler决策优选节点池，评估节点池1优先级高于节点池2，因此优选节点池1执行本次扩容。                                              |
  | priority-ratio | 组合策略，优先级排序为：priority \> priority-ratio \> least-waste \> random。 基于priority策略的资源碎片重调度场景化配套策略，即在同优先级场景下，优先选择扩容后可使节点可分配资源的CPU/内存比更接近于所有已调度Pods的申请的CPU/内存比。                                                                                                                                                               | 此策略基于集群中全局Pods/Nodes全局资源而非仅扩容节点部分，主要配套重调度等相关能力降低集群整体资源碎片率，无相关配套独立使用场景不建议使用。                                                                                                                                                                                                                                                                                                                                                                                           | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，评估节点池1和节点池2中扩容的节点均可调度部分Pending Pods。  3. autoscaler决策优选节点池，评估Pod的CPU/内存比为1:4，节点池1中的节点规格为2U8G（CPU/内存比为1:4），节点池2中的节点规格为2U4G（CPU/内存比为1:2）。因此优选节点池1执行本次扩容。   |
  | topology-balance | 组合策略，优先级排序为：topology-balance \> least-waste \> random。 基于不同可用区节点数量均衡的策略，即优先选择节点数量少的AZ进行扩容，尽可能保证各个AZ间的节点数量均衡。                                                                                                                                                                                                        | 使用topology-balance策略时，节点池优先级不生效。 在触发节点扩容时，可能同时扩容多个节点。本策略无法将一次性扩容的多个节点均分至各AZ，只保证多次扩容后，各AZ间节点数趋于均衡。                                                                                                                                                                                                                                                                                                                                        | 假设集群中节点池1和节点池2启用了弹性伸缩，且均未达到扩容上限。当工作负载扩容副本数时，扩容策略如下： 1. Pending Pods触发autoscaler决策扩容流程。  2. autoscaler模拟调度阶段，在开启弹性伸缩的节点池中，评估每个AZ的节点数。  3. autoscaler决策优选节点池，选择节点数量最少的AZ进行扩容。若两个AZ存在相同的节点数，则根据下一优先级的least-waste策略进行排序。                                        |
     
  
 
