1. 简介
Kubernetes默认调度器基于预选和优选策略进行调度,将Pod调度到最合适到节点上,但是在调度完成后,一个Pod是否仍然很适合当前Pod,就存在变数了,毕竟集群和节点是在实时变化到,所以,有必要将一个running到pod重新调度到更合适到节点上,这个组件就是Descheduler,反调度。
2. 何时进行反调度
一般来说,以下情况需要用到反调度:
- 一些节点变的低负载或者高负载
- 调度时的策略决策基于当时的集群状态,已经不适合当前集群,比如污点、labels的改变、pod和node的亲和、反亲和的改变;
- 一些nodes变为failed状态,节点上的pods迁往其节点;
- 集群中新增了节点。
3.当前不支持的特性
- 被驱逐的pod,仍由Kubernetes 默认调度器负责调度,Descheduler不会接管这类Pod。
- 开源实现没有基于监控,而是和Kubernetes默认调度器保持一致,根据requests来判断,否则容易和默认调度器产生mismatch,比如被descheduler驱逐的pod,又被scheduler给调度回来了,当Kubernetes默认调度器支持了基于监控的调度,Deschedudler也会支持。
4.七种可配置的策略
默认这些策略都是打开的。
RemoveDuplicates:保证一个RS、Deploy、RC、Job包含的pod,在一个节点上只有一个副本。
LowNodeUtilization:发现低利用率低node,如果同时有其他node希望驱逐pod,则会被调度到这些低利用率的node上面。
RemovePodsViolatingInterPodAntiAffinity:驱逐违背了pod亲和性的Pod,通常发生在先创建了容器,后创建了反亲和性。
RemovePodsViolatingNodeAffinity:通常发生在节点的亲和性发生改变的时候。
RemovePodsViolatingNodeTaints:驱逐违反了污点机制的Pod。
RemovePodsHavingTooManyRestarts:驱逐过多restart的Pod。
PodLifeTime:驱逐生命周期长于指定值的Pod。
5. 关于动态调度器
第3小节提到一个关于反调度器的缺点:
- 开源实现没有基于监控,而是和Kubernetes默认调度器保持一致,根据requests来判断,否则容易和默认调度器产生mismatch,比如被descheduler驱逐的pod,又被scheduler给调度回来了。
一种规避方式是,使用动态调度器。
Kubernetes 默认调度器使用节点上Pod申请的requests的值作为该资源使用情况,这种资源判断标准,是静态的,在实际生产环境,往往会出现request使用率较低的node,负载偏高,而request使用率较高的node,负载偏低。为了解决这类问题,引入了“动态调度”的概念,旨在将Pod调度到实际负载较低的节点上面。
一种动态调度器的实现方式:
在每个节点上部署动态调度器agent,其负责从监控系统(如Prometheus)收集Node节点的负载信息,并patch到Node节点的annotation上面;
动态调度器本身则在预选和优选两个阶段(如基于Kubernetes scheduler extender),根据节点上patch的annoation信息,筛选出更适合的节点。在预选阶段,过滤掉实际负载较高的节点,在优选阶段,根据节点上patch的annotation信息,根据计算的cpu和内存使用率为该节点打分,从而更精准的、基于实时监控进行调度。