ack-koordinator组件提供负载热点打散重调度能力,可以感知集群内节点负载的变化,自动优化超过负载水位安全阈值的节点,防止出现负载极端不均衡的情况。本文介绍如何使用负载热点打散重调度及其高级配置参数。
使用限制
仅支持ACK集群Pro版。具体操作,请参见创建ACK托管集群。
使用负载热点打散重调度,需满足以下版本要求。
组件
版本要求
ACK调度器版本
v1.22.15-ack-4.0及以上,v1.24.6-ack-4.0及以上
ack-koordinator(ack-slo-manager)
v1.1.1-ack.1及以上
Helm版本
v3.0及以上
费用说明
ack-koordinator组件本身的安装和使用是免费的,不过需要注意的是,在以下场景中可能产生额外的费用:
ack-koordinator是非托管组件,安装后将占用Worker节点资源。您可以在安装组件时配置各模块的资源申请量。
ack-koordinator默认会将资源画像、精细化调度等功能的监控指标以Prometheus的格式对外透出。若您配置组件时开启了ACK-Koordinator开启Prometheus监控指标选项并使用了阿里云Prometheus服务,这些指标将被视为自定义指标并产生相应费用。具体费用取决于您的集群规模和应用数量等因素。建议您在启用此功能前,仔细阅读阿里云Prometheus计费说明,了解自定义指标的免费额度和收费策略。您可以通过账单和用量查询,监控和管理您的资源使用情况。
负载热点打散重调度介绍
以下介绍负载热点打散重调度相关的概念。
负载感知调度
调度器支持负载感知调度,能够在调度时选择负载较低的节点运行新的Pod。节点的利用率会随着时间、集群环境变化、工作负载的流量或请求等动态变化,继而导致集群内节点间原本负载均衡的情况被打破,甚至有可能出现极端负载不均衡的情况,影响到工作负载运行时质量。ack-koordinator组件提供重调度能力,防止负载出现极端不均衡的情况。通过将负载感知调度和热点打散重调度结合使用,可以获得集群良好的负载均衡效果。关于负载感知调度,请参见使用负载感知调度。
koord-descheduler模块工作原理
ack-koordinator组件提供koord-descheduler模块,其中LowNodeLoad插件负责感知负载水位并完成热点打散重调度工作。与Kubernetes原生的Descheduler的插件LowNodeUtilization不同,LowNodeLoad是根据节点真实利用率决策重调度,而LowNodeUtilization是根据资源分配率决策重调度。
模块执行过程
koord-descheduler模块周期性运行,每个周期内的执行过程分为以下三个阶段。
数据收集:获取集群内的节点和工作负载信息,以及相关的资源利用率数据。
策略插件执行。
下文以LowNodeLoad为例。
筛选负载热点节点。关于节点分类,请参见下文LowNodeLoad负载水位参数说明。
遍历热点节点,从中筛选可以迁移的Pod,并进行排序。关于Pod打分排序,请参见下文Pod打分策略。
遍历每个待迁移的Pod,检查其是否满足迁移条件,综合考虑集群容量、资源利用率水位、副本数比例等约束。详细信息,请参见下文负载热点打散重调度策略说明。
若满足条件则将Pod归类为待迁移副本,若不满足则继续遍历其他Pod和热点节点。
容器驱逐迁移:针对待迁移的Pod发起Evict驱逐操作。关于Evict驱逐,请参见Evict驱逐。
LowNodeLoad负载水位参数说明
LowNodeLoad插件有两个重要的参数:
highThresholds:负载的热点水位,超过该阈值的节点上的Pod将参与重调度。建议您同时开启调度器的负载感知调度能力,请参见策略说明。关于两者如何搭配使用,请参见负载感知调度和热点打散重调度如何搭配使用?。
lowThresholds:负载的空闲水位,低于该阈值的节点上的Pod不会被重调度。
以下图为例,将lowThresholds设置为45%,将highThresholds设置为70%,那么节点的分类标准如下。同理,如果lowThresholds和highThresholds的值发生变更,节点的分类标准也会相应发生变化。
资源利用率数据默认每分钟更新一次,粒度为最近5分钟的平均值。
空闲节点(Idle Node):资源利用率低于45%的节点。
正常节点(Normal Node):资源利用率高于等于45%且低于等于70%的节点。此节点的负载水位区间是期望达到的合理区间范围。
热点节点(Hotspot Node):资源利用率高于70%的节点。热点节点将驱逐一部分Pod,降低负载水位,使其不超过70%。
负载热点打散重调度策略说明
策略名称 | 说明 |
热点检查重试次数策略 | 为了确保热点识别的准确性,避免部分毛刺监控数据触发应用频繁迁移,koord-descheduler支持为热点检查配置重试次数。只有节点连续多次触发阈值时才会识别为热点节点。 |
节点排序策略 | 在识别到的热点节点中,koord-descheduler会按资源用量从高到低的顺序,依次对节点发起重调度。其中,节点排序过程中会依次比较内存资源用量和CPU资源用量,优先选取资源用量更高的节点。 |
Pod打分策略 | 对于每个热点节点,koord-descheduler会对其中的Pod逐个打分排序,依次发起驱逐操作,将其迁移到空闲节点上。比较顺序如下:
说明 若您对Pod的驱逐顺序有要求,建议您考虑对Pod配置不同的优先级或QoS。 |
筛选策略 | koord-descheduler模块支持为Pod和Node配置多种筛选参数,方便您在使用过程中进行灰度控制。
|
前置检查策略 | koord-descheduler模块支持在Pod迁移前提供前置检查能力,确保每个Pod的迁移过程尽量安全。
|
迁移流量控制策略 | 为了满足Pod在迁移过程中应用的高可用要求,koord-descheduler模块还提供多种类型的限制能力,支持配置节点维度、命名空间维度以及工作负载维度下处于迁移状态Pod的最大数量。此外,它还提供基于时间窗口的流控机制,保证同一Workload下Pod的迁移不会过于频繁。koord-descheduler同样兼容K8s社区的干扰预算机制PDB(Pod Disruption Budgets),支持配置更精细的管理策略来保障工作负载的高可用。关于干扰预算机制,请参见干扰预算机制。 |
可观测性策略 | 您可以通过Event观测重调度的迁移过程,并在详细信息中查看迁移的具体原因和当前状态。样例如下。
|
步骤一:安装或修改组件ack-koordinator并开启重调度
未安装ack-koordinator组件
安装ack-koordinator组件,并在安装组件 ack-koordinator(ack-slo-manager)页面选中ack-koordinator开启重调度模块。安装ack-koordinator组件,请参见安装ack-koordinator组件。
已安装ack-koordinator组件
修改ack-koordinator组件,并在ack-koordinator参数配置页面选中ack-koordinator开启重调度模块。修改ack-koordinator组件,请参见修改ack-koordinator组件。
步骤二:开启负载热点打散重调度插件
使用如下YAML文件,创建koord-descheduler-config.yaml。
koord-descheduler-config.yaml是ConfigMap格式的对象,用于启用重调度插件LowNodeLoad。
执行如下命令,将配置更新到集群。
kubectl apply -f koord-descheduler-config.yaml
执行如下命令,重启重调度器模块koord-descheduler。
重启重调度器模块koord-descheduler后,koord-descheduler会使用修改后的最新配置。
kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 0 deployment.apps/ack-koord-descheduler scaled kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 1 deployment.apps/ack-koord-descheduler scaled
步骤三(可选):开启调度器负载均衡插件
开启调度器负载均衡插件,以获得集群良好的负载均衡效果。具体操作步骤,请参见步骤一:开启负载感知调度。
步骤四:验证重调度能力
下文以拥有3台104核 396 GB节点的集群为例进行说明。
使用如下YAML文件,创建stress-demo.yaml。
执行如下命令,创建压测Pod。
kubectl create -f stress-demo.yaml deployment.apps/stress-demo created
执行如下命令,观察Pod的状态,直到它开始运行。
kubectl get pod -o wide
预期输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES stress-demo-588f9646cf-s**** 1/1 Running 0 82s 10.XX.XX.53 cn-beijing.10.XX.XX.53 <none> <none>
可以看到,Pod
stress-demo-588f9646cf-s****
调度在节点cn-beijing.10.XX.XX.53
上。提升节点
cn-beijing.10.XX.XX.53
的负载水位,然后执行如下命令,检查每个Node节点的负载。kubectl top node
预期输出:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% cn-beijing.10.XX.XX.215 17611m 17% 24358Mi 6% cn-beijing.10.XX.XX.53 63472m 63% 11969Mi 3%
可以看到,节点
cn-beijing.10.XX.XX.53
的负载较高,为63%,已经超过配置的热点水位50%。节点cn-beijing.10.XX.XX.215
负载较低,为17%,低于配置的空闲水位20%。开启重调度。具体操作,请参见步骤二:开启负载热点打散重调度插件。
执行如下命令,观察Pod变化。
等待重调度器检查热点节点,并执行驱逐迁移操作。
说明判定为热点节点的默认条件为连续5次检查节点均超过热点水位,即10分钟。
kubectl get pod -w
预期输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES stress-demo-588f9646cf-s**** 1/1 Terminating 0 59s 10.XX.XX.53 cn-beijing.10.XX.XX.53 <none> <none> stress-demo-588f9646cf-7**** 1/1 ContainerCreating 0 10s 10.XX.XX.215 cn-beijing.10.XX.XX.215 <none> <none>
执行如下命令,观察Event。
kubectl get event | grep stress-demo-588f9646cf-s****
预期输出:
2m14s Normal Evicting podmigrationjob/00fe88bd-8d4c-428d-b2a8-d15bcdeb**** Pod "default/stress-demo-588f9646cf-s****" evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)" 101s Normal EvictComplete podmigrationjob/00fe88bd-8d4c-428d-b2a8-d15bcdeb**** Pod "default/stress-demo-588f9646cf-s****" has been evicted 2m14s Normal Descheduled pod/stress-demo-588f9646cf-s**** Pod evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)" 2m14s Normal Killing pod/stress-demo-588f9646cf-s**** Stopping container stress
预期输出为迁移记录,可以看出结果符合预期。热点节点上的Pod被重调度到其他节点。
高级配置参数
koord-descheduler模块高级配置参数介绍
koord-descheduler的所有参数配置以ConfigMap形式提供,以下展示了负载热点打散重调度的高级配置参数格式。
koord-descheduler系统配置
参数 | 类型 | 取值 | 说明 | 示例值 |
dryRun | boolean |
| 只读模式开关,开启后将不会发起Pod迁移。 | false |
deschedulingInterval | time.Duration | >0s | 重调度执行周期。 | 120s |
驱逐迁移控制配置
参数 | 类型 | 取值 | 说明 | 示例值 |
maxMigratingPerNode | int64 | ≥0(默认值为2) | 每个节点处于迁移状态的Pod的最大数量。0表示不限制。 | 2 |
maxMigratingPerNamespace | int64 | ≥0(默认不限制) | 每个命名空间处于迁移状态的Pod的最大数量。0表示不限制。 | 1 |
maxMigratingPerWorkload | intOrString | ≥0(默认值为10%) | 每个工作负载(例如Deployment)中处于迁移状态的Pod的最大数量或百分比。0表示不限制。 若工作负载只有单副本,则不参与重调度。 | 1或10% |
maxUnavailablePerWorkload | intOrString | ≥0(默认值为10%),且小于工作负载对应的副本总数 | 每个工作负载(例如Deployment)最大不可用副本数或百分比。0表示不限制。 | 1或10% |
evictLocalStoragePods | boolean |
| 是否允许配置了HostPath或EmptyDir的Pod参与重调度。出于安全考虑,默认不开启。 | false |
objectLimiters.workload | 结构体,数据格式为:
|
| 工作级别Pod迁移的流量控制。
|
表示5分钟内单个工作负载最多迁移1个副本。 |
LowNodeLoad插件配置
参数 | 类型 | 取值 | 说明 | 示例值 |
highThresholds | map[string]float64 说明 支持CPU和内存两个维度,值的单位为百分比。 | [0,100] | 表示负载的热点水位,超过该阈值的节点上的Pod将参与重调度。 说明 可以和调度器的负载感知调度能力搭配使用,将节点筛选参数loadAwareThreshold配置为相同的值,调度器会拒绝将Pod调度到该热点节点上,详情请参见策略说明。 |
|
lowThresholds | map[string]float64 说明 支持CPU和内存两个维度,值的单位为百分比。 | [0,100] | 表示负载的空闲水位。低于该阈值的节点上的Pod不会被重调度。 |
|
anomalyCondition.consecutiveAbnormalities | int64 | >0(默认值为5) | 热点检查重试次数。连续多个执行周期检查后,均超过highThresholds的节点,才会被判定为热点节点。热点节点发生驱逐后会重新计数。 | 5 |
evictableNamespaces |
| 集群内的命名空间 | 可以参与重调度的Namespace,不填表示所有Pod全部可参与。 支持配置include和exclude策略。两种策略需二选一。
|
|
nodeSelector | metav1.LabelSelector | 关于LabelSelector的格式,请参见Labels and Selectors | 通过LabelSelector选择目标节点。 | 分为两种方式,一种是指定单个节点池时的配置方式,一个是指定多个节点池时的配置方式。
|
podSelectors | 由PodSelector组成的List,支持配置多组Pod。PodSelector的数据格式为:
| 关于LabelSelector的格式,请参见Labels and Selectors | 通过LabelSelector选择开启重调度的Pod。 |
|
常见问题
节点利用率阈值已经达到阈值,但是节点上Pod没有被驱逐怎么办?
出现这种情况时,一般可能是有以下几种原因,请参考对应的解决方法进行调整。
原因分类 | 原因描述 | 解决方法 |
组件配置未生效 | 开启范围未指定 | 重调度器配置中包含Pod和节点的开启范围配置,请检查对应的命名空间和节点是否开启。 |
重调度器配置修改后未重启 | 重调度器配置修改后,需要对其进行重启才能生效。关于重启重调度器,请参见步骤二:开启负载热点打散重调度插件。 | |
节点状态不满足条件 | 节点的平均利用率长时间低于阈值 | 重调度器会持续对利用率监控一段时间,并对监控数据做平滑均值处理,因此只有节点持续超过阈值才会触发重调度,默认为10分钟左右。而 |
集群内剩余的容量不足 | 在对Pod驱逐前,重调度器会对集群内其他节点进行检查,确保容量充足才会进行迁移。例如选择了一个规格为8 Core 16 G的Pod准备驱逐,而集群所有节点的空闲容量均低于该值,出于安全考虑重调度器则不会对其迁移。请考虑增加节点,确保集群容量充足。 | |
工作负载属性约束限制 | 工作负载为单副本 | 为了保证单副本应用的高可用,这类Pod默认不参与重调度。如果您评估此类单副本应用后,希望该Pod参与重调度,请给Pod或者工作负载(如Deployment或StatefulSet)的TemplateSpec中追加Annotation 说明 该Annotation配置仅支持v1.2.0-ack1.3及更早版本。 |
Pod指定了HostPath或EmptyDir | 出于安全考虑,这类指定了HostPath或EmptyDir的Pod默认不参与重调度。如果需要对其进行迁移,可以参考evictLocalStoragePods配置允许其参与重调度。详细信息,请参见驱逐迁移控制配置。 | |
不可用或迁移中的副本数量过多 | 当工作负载(如Deployment或StatefulSet)的不可用或迁移中的副本数超过了限制配置(maxUnavailablePerWorkload或maxMigrationPerWorkload)。例如 maxUnavailablePerWorkload和maxMigrationPerWorkload设置为20%,Deployment的期望副本数设置为10,当前正好有2个Pod正在被驱逐或者正在发布,重调度器就不会对其发起驱逐。请等待Pod驱逐或发布完成,或将以上两个配置调大。 | |
副本数量约束配置错误 | 当工作负载的副本总数小于等于最大迁移数量配置maxMigrationPerWorkload或最大不可用数量配置maxUnavailablePerWorkload时,出于安全考虑重调度器将不会对其进行重调度。请将以上两个配置调小或修改为百分比模式。 |
重调度器频繁重启是什么原因?
重调度器的配置ConfigMap格式错误或不存在,请参考高级配置参数检查ConfigMap文件内容和格式并进行修改,修改后重启重调度器。重启重调度器,请参见步骤二:开启负载热点打散重调度插件。
负载感知调度和热点打散重调度如何搭配使用?
开启热点打散重调度后,负载热点上的Pod将会被驱逐。对于上层控制器(例如Deployment)新建的Pod,调度器会根据其配置选择合适的节点进行调度。为了获得更好的负载均衡效果,建议您同时为调度器开启负载感知调度能力,请参见使用负载感知调度。
配置时,建议您将负载感知调度中的节点筛选功能参数loadAwareThreshold配置为与热点打散重调度器的highThresholds参数相同的值,具体请参见策略说明。当节点的负载超过highThresholds时,重调度器将驱逐该节点上的Pod,而调度器则通过loadAwareThreshold拒绝新的Pod被调度到该热点节点上。否则,经驱逐的Pod可能重新被调度到原来的节点,尤其是在Pod指定了节点调度范围,但对应的节点数量较少且利用率较为接近时。
重调度参考的利用率算法是什么?
重调度器会持续对利用率监控一段时间,并对监控数据做平滑均值处理,因此只有节点持续超过阈值才会触发重调度,默认为10分钟左右。此外对于内存资源维度,重调度器参考的内存用量排除了page cache,因为这部分资源是可以被操作系统回收的,而通过kubectl top node
返回的利用率是包含page cache的,您可以通过使用阿里云Prometheus监控查看真实的内存用量信息。