节点组扩缩容常见问题
弹性伸缩FAQ
当集群的容量规划无法满足应用Pod调度时,您可以使用CCE提供的节点弹性伸缩功能,自动扩缩节点资源以进行调度容量的补充。
弹性扩缩容的扫描频率是多少?
30秒
扩缩容最大最小节点数的设置范围为多大?
最小节点数需要大于等于0,最大节点数需要小于等于当前集群节点数限额(该限额可以通过提交工单提升)。最大最小节点数将会限制自动扩缩容的范围,但是不会限制用户手动发起的扩缩容行为。
弹性扩容时创建节点的配置如何决定?
自动扩容时,将会按照当前集群中最主流的节点配置类型创建节点,即当前集群中节点数最多的配置类型。
如何防止特定节点被缩容释放?
以下类型的节点不会被缩容释放:
- 节点上有 pod 被 PodDisruptionBudget 控制器限制。
- 节点上的 pod 不是被控制器创建,例如不是被 deployment, replica set, job, stateful set 创建。
- 节点上有 pod 使用了本地存储
- 节点上 pod 驱逐后无处可去,即没有其他 node 能调度这个 pod
- 节点有注解:"cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"
阈值是如何选择与判断的?
在一个集群中,部分热点节点的利用率可能较高,而其他节点的利用率可能较低。
- 如果根据整个集群的平均资源利用率来决定是否弹性伸缩,使得热点节点的差异被平均,那么会造成对热点节点的扩缩不够及时。
- 如果依据最高的节点利用率来决定是否弹性伸缩,那么会造成弹出资源的浪费,影响集群的整体服务。
弹出实例后如何缓解压力?
在Kubernetes集群中,应用以Pod为最小单元部署在集群的不同节点上。当一个Pod资源利用率较高时,即使该Pod所在的节点或者集群触发了弹性扩容,但该应用的Pod数量以及Pod对应的Limit并没有发生变化,节点负载的压力也无法转移到新扩容的节点上。
如何判断节点的弹出?
节点伸缩会监听Pod是否处于调度失败的状态,以判断是否需要触发扩容。当Pod由于调度资源不足而调度失败时,节点伸缩会开始模拟调度,计算在开启弹性的节点组中哪个节点组可为这些Pod提供所需的节点资源,并在满足需求时弹出相应的节点。
说明 模拟调度时将一个开启弹性的节点组作为一个的抽象节点,开启弹性的节点组中配置的机型规格对应会成为抽象节点的CPU、内存或GPU的容量,且其配置的Label、Taint也会成为抽象节点的Label与Taint。模拟调度器会在调度模拟时,将该抽象节点纳入调度参考范围。符合调度条件时,调度模拟器会计算所需的节点数目,驱动节点组弹出节点。
如何判断节点的缩容?
节点伸缩仅缩容开启了弹性的节点组中的节点,无法管理静态节点(不在开启了弹性的节点组中的其他节点)。每个节点会单独判断是否进行缩容。当任意一个节点的调度利用率低于所设置的调度阈值时,就会触发缩容判断。此时,节点伸缩会尝试模拟驱逐节点上的负载,判断当前节点是否可以排水。部分特殊的Pod(例如kube-system命名空间的非DaemonSet Pod、PDB控制的Pod等)则会跳过该节点而选择其他的候选节点。当节点发生驱逐时,会先进行排水,将节点上的Pod驱逐到其他的节点,然后再下线该节点。
多个开启弹性的节点组之间如何选择?
不同开启弹性的节点组之间,实际上相当于不同的抽象节点之间的选择。和调度策略一样,开启弹性的节点组之间也存在打分机制。弹性组件首先筛选符合调度策略的节点,然后进一步根据affinity等亲和性策略进行选择。
如果基于上述策略无法选择合适的节点,默认情况下节点自动伸缩会通过least-waste的策略进行选择。least-waste策略的核心是模拟弹出节点后,找到剩余资源最少的节点。
说明 当有一个开启弹性的GPU节点组和开启弹性的CPU节点组同时可以弹出生效时,默认CPU会优先于GPU弹出。
如何提高弹性伸缩的成功率?
弹性伸缩的成功率主要取决于以下两个因素:
- 调度策略是否满足配置开启弹性的节点组后,您需要先确认该节点组可以承载的Pod的调度策略范围。如果无法直接判断,您可以通过
nodeSelector直接选择节点组的Label,来进行预弹模拟。 - 资源配置是否充分当模拟调度通过后,系统会选择开启弹性的节点组,以弹出实例。但开启弹性的节点组中配置的实例规格库存会直接影响是否可以成功弹出实例。因此,推荐您配置多个可用区、多个不同机型组合,以提高弹出成功率。
配置多实例规格的节点组是否支持扩容指定实例规格?
如果您的节点组同时配置了多个实例规格,扩容时无法指定扩容某个实例规格。cluster-autoscaler组件会以资源维度在各个实例规格中取最小值,作为资源计算的基准。
cluster-autoscaler组件可模拟判断的资源有哪些?
cluster-autoscaler组件已经支持以下资源的模拟和判断:
1cpu
2memory
3cce.baidubce.com/ip
4ephemeral-storage
5baidu.com/cgpu_core (仅共享GPU)
6baidu.com/cgpu_core(仅共享GPU)
7baidu.com/cgpu_decode(仅共享GPU)
8baidu.com/cgpu_encode(仅共享GPU)
9baidu.com/cgpu_memory_percent(仅共享GPU)
10nvidia.com/gpu
为什么节点弹性伸缩组件无法弹出节点?
请检查是否存在如下几种场景:
- 节点弹性伸缩仅对设置了弹性扩缩容的节点组生效,请确保节点自动伸缩功能已开启,并且已设置节点组的扩缩容模式为自动。
-
配置伸缩组的实例类型无法满足Pod的资源申请(Request)。实例规格给出的资源大小是实例的售卖规格,实际运行时CCE需要占用一定的节点资源来为kube组件和system进程预留资源,从而保证OS内核和系统服务、Kubernetes守护进程的正常运行。这会导致节点的资源总数Capacity与可分配的资源数Allocatable之间存在差异。cluster-autoscaler组件在进行节点扩容决策时,其内置的资源预留策略,更多信息请查看资源预留策略。
- 需要占用一定的节点资源来运行相关组件(例如kubelet、kube-proxy、Terway、Container Runtime等)。详细信息,请参见节点资源预留策略。
- 默认节点会安装系统组件,Pod的申请资源要小于实例的规格。
- 对可用区有约束的Pod,无法触发配置了多可用区的节点组扩容。
- 是否完整按照步骤执行了授权操作。授权操作是集群维度的,需要每个集群操作一次。
-
开启弹性伸缩的节点组中出现如下异常情况。
- 实例未加入到集群且超时。
- 节点NotReady且超时。
- 为保证后续扩缩准确性,弹性组件以阻尼方式处理异常情况,在处理完异常情况节点前,不进行扩缩容。
- 集群中没有节点,弹性伸缩组件cluster-autoscaler组件无法运行。建议您在创建节点组时至少配置2个节点,以确保集群组件的正常运行。
无法100%精确预估节点可用资源
由于实例底层系统会占用部分资源,因此实例可用内存会小于实例规格定义(请参见购买实例后查看内存大小,为什么和购买时的实例规格定义不一致?)。受此约束,cluster-autoscaler组件估算的节点可调度资源可能大于实际节点的可调度资源,无法100%精确预估。您在配置Pod Request时,需关注以下注意事项。
- 配置Pod Request取值时,资源申请总量需小于实例规格定义(包括CPU、内存、磁盘等)。建议Request总量不超过节点资源的70%。
- cluster-autoscaler组件在判断节点的资源是否充足时仅会考虑Kubernetes Pod(Pending Pod和DaemonSet Pod)资源。如果节点上存在非DaemonSet的Static Pod,需预先为此类Pod预留资源。
- 如果Pod资源申请占用的确较大(例如超过节点资源70%时),请提前测试并确认Pod是否可调度到同实例规格的节点上,保证可行性。
如果一个伸缩组内配置了多资源类型的实例规格,弹性伸缩时如何计算这个伸缩组的资源呢?
对于配置了多个实例规格的伸缩组,弹性伸缩组件以资源维度在各个实例规格中取最小值,作为资源计算的基准。
例如,如果一个伸缩组内配置了两种实例规格,一个是CPU 4核内存32 GB,另一个是CPU 8核内存16 GB。弹性伸缩组件认为这个伸缩组能保证的扩容出的CPU是4核内存16 GB的实例资源。因此如果状态为Pending的Pod的requests资源超出4核或者16 GB,则不会进行扩容。
如果您配置了多实例规格但需要考虑资源预留,请参见为什么节点自动伸缩组件无法弹出节点?
为什么为节点组设置自动扩缩容失败?
可能原因如下:
- 节点组中已有通过手动添加的节点,您需要先移除手动添加的节点。建议您创建新的开启弹性扩缩容的节点组。
- 节点组中有包年包月的实例。节点弹性伸缩功能不支持包年包月付费类型的节点。
为什么cluster-autoscaler组件无法缩容节点?
请检查是否存在如下几种场景:
- 节点Pod的资源申请(Request)阈值高于设置的缩容阈值。
- 节点上运行kube-system命名空间的Pod。
- 节点上的Pod包含强制的调度策略,导致其他节点无法运行此Pod。
- 节点上的Pod拥有PodDisruptionBudget,且到达了PodDisruptionBudget的最小值。
您可以在开源社区得到更多关于节点自动伸缩组件的常见问题与解答。
如何启用或禁用特定DaemonSet的驱逐?
cluster-autoscaler组件会根据是否开启 Daemonset Pod 排水配置决定是否驱逐DaemonSet Pods,这些配置是集群维度的,对集群中的DaemonSet Pods通用。如果想要对某个DaemonSet Pod指定是否需要被驱逐,可以对这个DaemonSet Pod添加Annotation"cluster-autoscaler.kubernetes.io/enable-ds-eviction":"true"。
类似的,DaemonSet Pod的Annotation中如果有"cluster-autoscaler.kubernetes.io/enable-ds-eviction":"false",则会显示禁止Cluster Autoscaler驱逐这个DaemonSet Pod。
说明
- 如果未开启DaemonSet Pod排水,此Annotation仅对非空节点的DaemonSet Pod有效。如果想开启空节点DaemonSet Pod,需要先开启DaemonSet Pod排水。
- 此Annotation需要在DaemonSet Pod上指定,而不是DaemonSet对象本身。
- 此Annotation对不属于任何DaemonSet的Pod没有影响。
- 默认情况下,Cluster Autoscaler对DaemonSet Pod的驱逐是非阻塞模式的,即不等待DaemonSet Pod驱逐完成后,就会执行后续流程。如需要Cluster Autoscaler等待指定DaemonSet Pod驱逐完成后再执行后续缩容流程,除以上启用配置外,请为相应Pod添加Annotation
"cluster-autoscaler.kubernetes.io/wait-until-evicted":"true"。
什么类型的Pod可以阻止cluster-autoscaler组件移除节点?
当Pod不是由原生Kubernetes Controller创建的Pod(例如非Deployment、ReplicaSet、Job、StatefulSet等对象创建的Pod),或者当节点上的Pod不能被安全地终止或迁移时,cluster-autoscaler组件可能会阻止移除这个节点。详细信息,请参见什么类型的Pod可以阻止CA移除节点?。
cluster-autoscaler组件是否支持CRD?
cluster-autoscaler组件目前仅支持Kubernetes标准对象,暂时不支持Kubernetes CRD
如何延迟cluster-autoscaler组件对不可调度Pod的扩容反应时间?
可以通过Annotationcluster-autoscaler.kubernetes.io/pod-scale-up-delay为每个Pod设置延迟扩容时间。如果Kubernetes没有在该延迟结束时调度它们,那么CA可能会考虑对它们进行扩展。Annotation示例:"cluster-autoscaler.kubernetes.io/pod-scale-up-delay": "600s"。
如何指定节点不被cluster-autoscaler组件缩容?
为目标节点配置Annotation "cluster-autoscaler.kubernetes.io/scale-down-disabled": "true",使其不被cluster-autoscaler缩容。添加Annotation的命令示例如下。
1kubectl annotate node <nodename> cluster-autoscaler.kubernetes.io/scale-down-disabled=true
cluster-autoscaler组件使用哪些调度策略来判断不可调度Pod能否调度到开启了弹性的节点组?
使用的调度策略如下所示。
- PodFitsResources
- GeneralPredicates
- PodToleratesNodeTaints
- NoDiskConflict
- CheckNodeCondition
- CheckNodeDiskPressure
- CheckNodeMemoryPressure
- CheckNodePIDPressure
- CheckVolumeBinding
- ready
- NoVolumeZoneConflict
