全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:节点自动伸缩

更新时间:Feb 23, 2024

ACK的自动伸缩能力是通过节点自动伸缩组件实现的,可以按需弹出以下按量计费的实例:普通实例、GPU实例和竞价付费实例,支持多可用区、多实例规格、多种伸缩模式,满足不同的节点伸缩场景。

工作原理

在Kubernetes中,节点自动伸缩的工作原理与传统意义上基于使用率阈值的模型有所差别,这也是很多开发者在从传统的IDC或者其他编排系统迁移到Kubernetes后最难理解的地方。

传统的弹性伸缩模型是基于使用率的,例如:一个集群中有3个节点,当集群中的节点CPU、内存使用率超过特定的阈值时,此时弹出新的节点。但当深入思考时会发现以下几个问题:

1.阈值是如何选择与判断的?

在一个集群中,部分热点节点的利用率会较高,而另外一个节点的利用率会很低。如果选择平均利用率的话可能会造成弹性伸缩的不及时。如果使用最低的节点的利用率,那么也会造成弹出资源的浪费。

2.弹出实例后是如何缓解压力的?

在Kubernetes中,应用是以Pod为最小单元,部署在集群的不同节点上的。当一个Pod资源利用率较高的时候,即便此时所在的节点或者集群的总量触发了弹性扩容,但是该应用的Pod数量以及Pod对应的Limit没有任何变化,那么负载的压力是无法转移到新扩容出的节点上的。

3.如何判断以及执行实例的缩容?

如果基于资源利用率的方式判断节点是否缩容,那么很有可能出现,Request很大,但是Usage很小的Pod被驱逐,当集群中这种类型的Pod较多时,会导致集群的调度资源被占满,部分Pod无法调度。

Kubernetes节点伸缩是怎么解决以上问题的呢?Kubernetes是通过调度与资源解耦的两层弹性模型来解决的。

基于资源的使用率来触发应用副本的变化,也就是调度单元的变化。而当集群的调度水位达到100%的时候会触发资源层的弹性扩容,当资源弹出后,无法调度的单元会自动调度到新弹出的节点上,从而降低整个应用的负载状况。以下介绍Kubernetes弹性伸缩的技术细节:

1.如何判断节点的弹出?

cluster-autoscaler是通过对处于Pending状态的Pod进行监听而触发的。当Pod处于Pending状态的原因是调度资源不足的时候,会触发cluster-autoscaler的模拟调度,模拟调度器会计算在配置的伸缩组中哪个伸缩组弹出节点后可以调度这些Pending的Pod。如果有伸缩组可以满足需求,那么就弹出相应的节点。

模拟调度就是将一个伸缩组当成一个抽象的Node,伸缩组中配置的机型规格对应会成为Node的CPU/内存/GPU的容量,然后设置伸缩组上面的Label、Taint,也就是Node的Label与Taint。模拟调度器会在调度模拟的时候,将该抽象的Node纳入调度参考。如果Pending的Pod可以调度到抽象的Node,那么就会计算所需的Node的数目,驱动伸缩组弹出节点。

2.如何判断节点的缩容?

首先只有弹性伸缩弹出的节点会被缩容,静态的节点是无法被cluster-autoscaler接管的。缩容的判断是通过每个节点单独判断的。当任意一个节点的调度利用率低于所设置的调度阈值时,会触发节点的缩容判断。此时cluster-autoscaler会尝试模拟驱逐节点上面的负载,判断当前节点是否可以排水彻底。有些特殊的Pod(kube-system命名空间的非DaemonSet Pod、PDB控制的Pod等),则会跳过该节点而选择其他的候选节点。当节点发生驱逐时,会先进行排水,将节点上的Pod驱逐到其他的节点,然后再下线该节点。

3.多个分组之间如何选择?

不同分组之间,实际上相当于不同的虚拟的Node之间的选择,和调度策略一样,这里也存在一个打分的机制。首先符合调度策略的Node会先过滤出来,在符合调度策略的Node中,会根据affinity等亲和性的策略进行选择。如果上述的策略都不存在,默认情况下cluster-autoscaler会通过least-waste的策略来进行抉择。least-waste的策略的核心就是模拟弹出节点后,剩余的资源最少。此外,有一个特别的场景,当有一个GPU的伸缩组和CPU的伸缩组同时可以弹出生效时,默认CPU会优先于GPU弹出。

4.如何提高弹性伸缩的成功率?

弹性伸缩的成功率主要取决于以下两个因素:

  • 调度策略是否满足

    首先在配置好伸缩组后,开发者需要先确认下该伸缩组可以承载的Pod的调度策略范围。如果无法直接判断,最简单的方式是通过nodeSelector直接选择伸缩组的Label进行预弹模拟。

  • 资源配置是否充分

    当模拟调度通过后,会选择伸缩组进行弹出,但是伸缩组中配置的ECS规格是否有库存会直接决定是否可以成功弹出实例。因此配置多个可用区、多个不同机型组合可以大大提高弹出成功率。

5.如何提高弹性伸缩的速度?

  • 方法一:可以通过极速模式加速弹出速度,当伸缩组预热后(已完成一次扩容和缩容),伸缩组即可进入极速伸缩模式。

  • 方法二:使用自定义镜像的方式,通过Alibaba Cloud Linux 2(原Alibaba Cloud Linux 2)作为基础镜像,可以大大提升IaaS层的资源交付速度(50%)。

注意事项

  • 在专有网络下创建的单个路由表可创建的自定义路由数限额是200条。如需更大的配额,请前往配额中心提交申请。关于其他资源的配额限制及升配详情,请参见依赖底层云产品配额限制

  • 单一规格的ECS库存容量波动较大,建议在伸缩组中配置多种同规格的实例类型,提高节点伸缩成功率。

  • 极速弹出模式在节点进入停机回收状态时,节点将进行停机,并处在NotReady状态,当再次伸缩弹出时,节点状态会变为Ready

  • 极速弹出模式的节点处在停机回收状态时,只收取磁盘的费用,不收取计算费用(不包含拥有本地盘的机型系列,例如,ecs.d1ne.2xlarge),在库存充裕的前提下可以极速启动。

  • 选择绑定EIP时,通过ECS控制台直接删除自动伸缩组扩容出的ECS节点会导致弹性公网EIP(Elastic IP Address)无法自动释放。

  • 由于节点标签和污点配置映射到伸缩组Tag后自动伸缩才可识别,并且伸缩组Tag有数目上限限制,开启自动伸缩的节点池配置的ECS标签、污点和节点标签的总数需要控制在12个之内。

步骤一:开启集群自动弹性伸缩

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择节点管理 > 节点池

  3. 节点池页面,单击集群自动弹性伸缩后面的去配置,即可开始自动伸缩相关的授权和配置。

    1.jpg

步骤二:授权

说明

以下开通ESS服务的操作仅供参考,实际请按照界面提示操作。

  1. 开通ESS服务。

    1. 单击提示对话框中弹性伸缩(Auto Scaling)链接,进入弹性伸缩服务ESS页面。

    2. 单击开通ESS服务,进入云产品开通页

    3. 选中我已阅读并同意复选框,单击立即开通

    4. 开通成功后,在开通完成页签,单击管理控制台,进入弹性伸缩服务ESS页面。

    5. 单击前往授权,进入云资源访问授权页面,配置对云资源的访问权限。

    6. 单击同意授权

  2. 授权角色。

    1. 根据步骤一:开启集群自动弹性伸缩弹出的自动伸缩配置对话框中授权引导链接进行授权。

      说明
      • ACK专有集群请根据页面引导对每个集群授权AliyunCSManagedAutoScalerRolePolicy

      • 对于ACK托管集群,请确保kube-system命名空间下保密字典内有addon.aliyuncsmanagedautoscalerrole.token。如果没有,请提交工单

        没有Token的情况下,默认通过WorkRole实现相关能力。您可以参见如何为集群WorkerRole添加AliyunCSManagedAutoScalerRolePolicy权限?,尝试通过为集群WorkerRole添加AliyunCSManagedAutoScalerRolePolicy权限的方法解决问题。

    2. 云资源访问授权页面,单击同意授权

步骤三:配置自动伸缩

  1. 集群自动弹性伸缩配置页面,填写以下信息,并单击确定

    配置

    说明

    备注

    节点池扩容顺序策略

    • 随机策略。如果可扩容节点池有多个,从中任意选择一个节点池进行扩容。

    • 默认策略。如果可扩容节点池有多个,从中选择一个资源浪费最少的节点池进行扩容。

    • 优先级策略。如果可扩容节点池有多个,会按照您自定义的伸缩组顺序,选择优先级高的节点池进行扩容。为节点池自定义扩容优先级,请参见优先级策略配置

      说明

      为节点池自定义扩容优先级,需要在节点池创建完成后再操作。

    无。

    弹性灵敏度

    集群自动弹性伸缩配置支持设置弹性灵敏度,以调整系统判断伸缩的间隔时间。目前支持15s、30s、60s、120s、180s和300s的选项,默认值是60s。

    无。

    允许缩容

    是否允许进行节点缩容。若设置为不允许缩容,缩容相关配置将不生效,请谨慎设置。

    无。

    缩容阈值

    cluster-autoscaler管理的伸缩组中,单个节点的资源申请值(Request)与单个节点资源容量的比值。当低于配置的阈值时,节点才可能被缩容。

    说明

    弹性伸缩中,扩容会基于调度自动触发,只需设置缩容条件即可。

    • 对于非GPU类型的节点,以下条件是缩容的必要条件。只有满足以下条件,节点才可能被缩容。如果不满足任意一个条件,节点都不会被缩容。

      • cluster-autoscaler管理的伸缩组中,单个节点的资源申请值(Request)与单个节点资源容量的比值低于缩容阈值

        说明

        节点的资源包括CPU和内存,它们的资源利用率必须都低于缩容阈值。

      • 时间满足缩容触发时延

      • 距离最近一次扩容已超过静默时间

    • 对于GPU类型的节点,以下条件是缩容的必要条件。只有满足以下条件,节点才可能被缩容。如果不满足任意一个条件,节点都不会被缩容。

      • cluster-autoscaler管理的伸缩组中,单个节点的资源申请值(Request)与单个节点的资源容量的比值低于GPU缩容阈值

        说明

        节点的资源包括CPU、内存和GPU资源,它们的资源利用率必须都低于缩容阈值。

      • 时间满足缩容触发时延

      • 距离最近一次扩容已超过静默时间

    GPU缩容阈值

    GPU类型实例的缩容阈值,当低于配置的阈值时,GPU类型节点才可能被缩容。

    缩容触发时延

    集群满足配置的缩容阈值时,在配置的缩容触发时延到达后,集群才有可能开始缩容。单位:分钟。默认情况下是10分钟。

    静默时间

    最近一次扩容后,弹性组件不执行缩容的时间。在静默时间内不缩容节点,但是仍然会判断节点是否可以缩容。超过静默时间后,如果节点满足了缩容条件且时间大于缩容触发时延的条件,则会被缩容。

    配置的静默时间为10分钟,缩容触发时延为5分钟。那扩容活动后的10分钟内自动伸缩不会缩容节点,但是系统会在静默时间10分钟内判断节点是否符合缩容条件。如果静默时间结束后,节点符合缩容条件且时间超过缩容触发时延5分钟,节点会被缩容。

    单击缩容高级配置,完成缩容高级配置。

    配置

    说明

    pod终止超时时间

    缩容节点时等待节点上Pod终止的最长时间(单位:秒)。

    pod最小副本数

    节点排水时允许每个副本集中Pod的最小数量。

    开启daemonset pod排水

    是否允许开启Daemonset Pod排水。若设置为开启Daemonset Pod排水,节点缩容时会驱逐节点上的Daemonset Pods。

    跳过有kube-system pod所在节点

    对于拥有kube-system命名空间下Pods的节点,是否允许节点自动缩容时将其跳过。

    说明

    开启跳过有kube-system pod所在节点,对DaemonSet Pods和Mirror Pods不生效。

  2. 单击页面右侧的创建节点池

  3. 创建节点池对话框,设置伸缩组的配置项。

    有关配置项的详细说明,请参见创建Kubernetes托管版集群。部分配置项说明如下:

    配置

    说明

    地域

    所创建伸缩组将要部署到的地域。与伸缩组所在集群的地域一致,不可变更。

    专有网络

    所创建伸缩组的网络,与伸缩组所在集群的网络一致。

    虚拟交换机

    所创建伸缩组的虚拟交换机,包含伸缩组的可用区及Pod地址段。

    自动伸缩

    根据需要选择弹性伸缩的节点资源类型(包含普通实例GPU实例共享GPU实例抢占式实例),与创建集群时所选择的节点类型一致。

    实例规格

    伸缩组内实例的规格。

    已选规格

    所选择的伸缩组的实例规格,最多可以选择10种实例规格。

    系统盘

    伸缩组的系统盘。

    挂载数据盘

    是否在创建伸缩组时挂载数据盘,默认情况下不挂载。

    实例数量

    伸缩组所包含的实例数量。

    说明
    • 实例不包含客户已有的实例。

    • 默认情况,实例的最小值是0台,超过0台的时候,集群会默认向伸缩组中添加实例,并将实例加入到伸缩组对应的Kubernetes集群中。

    操作系统

    在开启自动伸缩时,支持选择Alibaba Cloud Linux、CentOS、Windows镜像、Windows Core镜像。

    说明

    当所选镜像是Windows镜像或Windows Core镜像时,系统将自动配置污点(Taints){ effect: 'NoSchedule', key: 'os', value: 'windows' }

    密钥对

    登录伸缩后的节点时所使用的密钥对。可以在ECS控制台新建密钥对。

    说明

    目前只支持密钥对方式登录。

    RDS白名单

    弹性伸缩后的节点可以访问的RDS实例。

    节点标签

    在集群中添加节点标签(Label)后,会自动添加到弹性伸缩扩容出的节点上。

    扩缩容策略

    • 优先级策略:根据以上配置的虚拟交换机的优先级进行扩缩容(选择的虚拟交换机的顺序,由上到下优先级递减)。当优先级较高的虚拟交换机所在可用区无法创建ECS实例时,自动使用下一优先级的虚拟交换机创建ECS实例。

    • 成本优化策略:按vCPU单价从低到高尝试创建。当伸缩配置已设置抢占式计费方式的多实例规格时,优先创建对应抢占式计费实例。当抢占式计费实例规格由于库存等原因无法创建时,自动尝试以按量付费的方式创建。

      付费类型抢占式实例时,还可配置以下参数:

      • 按量实例所占比例%:节点池实例中按量实例应占的比例,取值范围为[0,100]。

      • 开启抢占式实例补偿:开启后,当收到抢占式实例将被回收的系统消息时(即抢占式实例被回收前5分钟左右),伸缩组将尝试创建新的实例,替换掉将被回收的抢占式实例。

      • 允许按量实例补偿:开启后,如果因价格或库存等原因无法创建足够的抢占式实例,伸缩组将自动尝试创建按量实例,以满足ECS实例数量要求。

    • 均衡分布策略:只有设置多个专有网络交换机时,均衡分布策略才能生效。在伸缩组指定的多可用区(即指定多个专有网络交换机)之间均匀分配ECS实例。如果由于库存不足等原因造成可用区之间不平衡,您可以再次进行均衡操作,以平衡资源的可用区分布。

    重要

    节点池创建完成后,扩缩容策略不支持编辑。

    伸缩模式

    支持标准模式极速模式

    • 标准模式:根据资源申请值的使用量,通过创建、释放ECS实例的方式进行伸缩。

    • 极速模式:通过创建、停机、启动的方式进行伸缩,提高再次伸缩的速度。

      说明

      极速模式实例停机再次启动时,如果启动失败不会自动释放实例,请注意按需手动释放。

    污点(Taints)

    添加污点后,集群将不会将Pod调度到该节点上。

  4. 单击确认配置,创建伸缩组。

  5. (可选)优先级策略配置。在节点池页面,单击集群自动弹性伸缩右侧的编辑。设置节点池扩容优先级单击确定,完成优先级策略配置。

    说明

    优先级取值[1,100],必须为正整数。

预期结果

  1. 节点池页面,可以看到已开启自动伸缩的节点池。

    集群自动弹性伸缩..png

  2. 集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情

  3. 在集群管理页左侧导航栏,选择工作负载 > 无状态

  4. 无状态页面,选择kube-system命名空间,可以看到名称为cluster-autoscaler的组件,表示伸缩组已创建成功。

常见问题

为什么节点自动伸缩组件无法弹出节点?

请检查是否存在如下几种场景:

  • 配置伸缩组的实例类型无法满足Pod的资源申请(Request)。ECS实例规格给出的资源大小是实例的售卖规格,实际运行时ACK需要占用一定的节点资源来为kube组件和system进程预留资源,从而保证OS内核和系统服务、Kubernetes守护进程的正常运行。这会导致节点的资源总数Capacity与可分配的资源数Allocatable之间存在差异。详细信息,请参见节点资源预留策略

    另外,默认节点会安装系统组件,Pod的申请资源要小于实例的规格。

  • 对可用区有约束的Pod,无法触发配置了多可用区的节点池扩容。

  • 是否完整按照步骤执行了授权操作。授权操作是集群维度的,需要每个集群操作一次。关于授权,请参见步骤二:授权

  • 开启自动伸缩的节点池中出现如下异常情况。

    • 实例未加入到集群且超时。

    • 节点未ready且超时。

    为保证后续扩缩准确性,弹性组件以阻尼方式处理异常情况,在处理完异常情况节点前,不进行扩缩容。

为什么节点自动伸缩组件无法缩容节点?

请检查是否存在如下几种场景:

  • 节点Pod的资源申请(Request)阈值高于设置的缩容阈值。

  • 节点上运行kube-system命名空间的Pod。

  • 节点上的Pod包含强制的调度策略,导致其他节点无法运行此Pod。

  • 节点上的Pod拥有PodDisruptionBudget,且达到了PodDisruptionBudget的最小值。

您可以在开源社区得到更多关于节点自动伸缩组件的常见问题与解答。

多个伸缩组在弹性伸缩的时候是如何被选择的?

在Pod无法调度时,会触发弹性伸缩组件的模拟调度逻辑,根据伸缩组配置的标签、污点以及实例规格等信息进行判断。当配置的伸缩组可以模拟调度Pod的时候,会选择进行节点弹出。当有多个伸缩组同时满足模拟调度条件的时候,默认采用最少浪费原则,即根据模拟弹出后节点上剩余的资源最小进行抉择。

什么类型的Pod可以阻止CA移除节点?

cluster-autoscaler使用了哪些调度策略来判断不可调度Pod能否调度到开启自动伸缩节点池?

使用的调度策略如下所示。

  • PodFitsResources

  • GeneralPredicates

  • PodToleratesNodeTaints

  • MaxGCEPDVolumeCount

  • NoDiskConflict

  • CheckNodeCondition

  • CheckNodeDiskPressure

  • CheckNodeMemoryPressure

  • CheckNodePIDPressure

  • CheckVolumeBinding

  • MaxAzureDiskVolumeCount

  • MaxEBSVolumeCount

  • ready

  • MatchInterPodAffinity

  • NoVolumeZoneConflict

如何为集群WorkerRole添加AliyunCSManagedAutoScalerRolePolicy权限?

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 单击集群资源页签,然后单击Worker RAM 角色后面的链接。

  3. RAM控制台,单击精确授权

  4. 精确授权面板,默认选择系统策略,输入系统策略名称为AliyunCSManagedAutoScalerRolePolicy,然后单击确定

  5. 精确授权面板,单击关闭。刷新页面,可以看到新增的权限。

  6. 手动重启kube-system命名空间下的deployment cluster-autoscaler,以便权限立即生效。