为了衡量动态调度器对增强 Pod 调度到低负载节点的提升效果,结合调度器的实际调度结果,获取所有调度到的节点在调度时刻的的 CPU/内存利用率以后统计以下几个指标:
cpu_utilization_total_avg :所有调度到的节点 CPU 利用率平均值。
memory_utilization_total_avg :所有调度到的节点内存利用率平均值。
effective_dynamic_schedule_count :有效调度次数,当调度到节点的 CPU 利用率小于当前所有节点 CPU 利用率的中位数,我们认为这是一次有效调度,effective_dynamic_schedule_count 加 0.5分,对内存也是同理。
total_schedule_count :所有调度次数,每次新的调度累加1。
effective_schedule_ratio :有效调度比率,即 effective_dynamic_schedule_count/total_schedule_count
下面是在同一集群中不开启动态调度和开启动态调度各自运行一周的指标变化,可以看到对于集群调度的增强效果。
cpu_utilization_total_avg 0.30 0.17
memory_utilization_total_avg 0.28 0.23
effective_dynamic_schedule_count 2160 3620
total_schedule_count 7860 7470
effective_schedule_ratio 0.273 0.486
Descheduler
现有的集群调度场景都是一次性调度,即一锤子买卖。后续出现节点 CPU 和内存利用率过高,也无法自动调整 Pod 的分布,除非触发节点的 eviction manager 后驱逐,或者人工干预。这样在节点 CPU/内存利用率高时,影响了节点上所有 Pod 的稳定性,而且负载低的节点资源还被浪费。
针对此场景,借鉴 K8s 社区 Descheduler 重调度的设计思想,给出基于各节点 CPU/内存实际利用率进行驱逐的策略。
架构Descheduler 从 apiserver 中获取 Node 和 Pod 信息,从 Prometheus 中获取 Node 和 Pod 监控信息,然后经过Descheduler 的驱逐策略,驱逐 CPU/内存使用率高的节点上的 Pod ,同时我们加强了 Descheduler 驱逐 Pod 时的排序规则和检查规则,确保驱逐 Pod 时服务不会出现故障。驱逐后的 Pod 经过动态调度器的调度会被调度到低水位的节点上,实现降低高水位节点故障率,提升整体资源利用率的目的。
产品能力 产品依赖依赖基础的节点监控组件 node-exporter 和Prometheus。Prometheus 支持托管和自建两种方式,使用托管方式可以一键安装 Descheduler,使用自建 Prometheus 也提供了监控指标配置方法。
组件配置Descheduler 根据用户配置的利用率阈值,超过阈值水位后开始驱逐 Pod ,使节点负载尽量降低到目标利用率水位以下。
产品效果 通过 K8s 事件通过 K8s 事件可以看到 Pod 被重调度的信息,所以可以开启集群事件持久化功能来查看 Pod 驱逐历史。
节点负载变化在类似如下节点 CPU 使用率监控视图内,可以看到在开始驱逐之后,节点的 CPU 利用率下降。
最佳实践 集群状态拿一个客户的集群为例,由于客户的业务大多是内存消耗型的,所以更容易出现内存利用率很高的节点,各个节点的内存利用率也很不平均,未使用动态调度器之前的各个节点监控是这样的:
配置预选和优选阶段的参数如下: