kubernetes – 利用descheduler均衡POD分布

kube-scheduler调度POD是一次性决策的,一旦POD选定node运行起来,除非人工干预否则POD将永远运行在该node。

那么一个典型的问题就来了,当我们向集群新加入一个node时,POD并不会自动均衡到这个node,除非我们主动滚动发布以便让kube-scheduler做出新的决策。

类似的问题还有,我们通常希望同一个deployment的POD可以分布到不同的node上,然而集群中的资源碎片很有可能导致2个POD分布到一个node上,随着集群资源的自然变动,我们希望能有合适的机会重新进行打散。

那么,上述实际问题就需要引入一个新的组件叫做descheduler,由它来辅助kube-scheduler,对POD进行定期的二次打散整理,确保集群尽量调度均衡。

使用方法

descheduler配置与使用非常简单,也是K8S官方的准预备项目,理论上是可靠的。

项目地址:https://github.com/kubernetes-sigs/descheduler,把项目下载下来即可。

创建rbac

因为descheduler需要获取集群的pod/node等资源信息,以便做出决策,所以第一步就是配置rbac相关的东西,简单说就是创建serviceaccount与role,然后做一下两者的binding。

执行如下命令直接生效:

会得到一个kube-system命名空间下面的descheduler-sa账号,已经做好了资源授权。

创建configmap

descheduler的配置文件,通过configmap配置并挂载。

打开kubernetes/configmap.yaml,看一下descheduler支持的几个均衡策略:

它最多支持5种策略共同工作,每一个策略有独立的开关选项。

该配置文件只写了3个策略,也是比较好用的几个策略:

  • RemoveDuplicates:如果deployment的多个pod在同1个node上,那么就试图打散。
  • RemovePodsViolatingInterPodAntiAffinity:pod曾经与node亲和,而现在不再亲和了,那么对该pod尝试做迁移。
  • LowNodeUtilization:如果node上的cpu/memory/pods的request超过targetThresholds阈值,则认为该node负载太高,会尝试将其上的pod进行迁移,迁移的目标node需要低于thresholds阈值,这些node被认为是负载太低。

针对LowNodeUtilization策略,根据github中的说明:

1)thresholds的判断是必须cpu+mem+pod三个条件(都是百分比)同时满足才算作”低负载node”,其cpu/memory依据是request值。

2)targetThresholds判断依据是cpu or mem or pod任意一个超过阈值才算作”高负载node”。

pod会从”高负载node” 迁移至 “低负载node”,不满足2个条件的node不会做均衡处理。

有需要则调整,然后直接提交即可:

运行

理论上来说,descheduler还是凌晨业务低峰期执行比较靠谱,因此descheduler也被设计为一种一次性的JOB。

为了自动执行,我们使用cronjob来定时运行它。

打开kubernetes/cronjob.yaml:

可见,它挂载了configmap作为配置文件,配置了descheduler-sa的serviceaccount,并且禁止了并发执行。

默认是2分钟调度一次,我们根据自己修改cron表达式即可,比如改成每天凌晨执行。

镜像已经被墙,大家可以使用海外服务器下载镜像然后推送到dockerhub作替代,或者直接使用我备份的版本:owenliang1990/descheduler:v0.18.0。

直接提交它即可:

日志

cronjob会定时拉起一个Pod,我们可以修改Descheduler启动参数的日志级别调整–v 5,通过kubectl logs查看pod具体做了哪些决策。

调试

为了降低使用descheduler的风险(比如大面积的踢出POD),测试时使用启动参数–dry-run,令其仅做决策不做真正的POD驱逐,根据日志验证在不同集群上的具体表现,辅助我们调整驱逐的阈值参数。

我认为正常情况下,仅仅基于CPU指标来做均衡即可,不需要考虑Mem/POD个数,否则低负载节点的多个thresholds条件比较难以同时成立。

实测下来,descheduler会扫描每个node,先判断node的cpu/mem/pods是否同时小于thresholds,如果成立则认为该node是低负载的;如果不成立则进一步判断cpu/mem/pods是否任意指标大于targetThresholds,如果成立则认为是高负载的;其他情况node什么也不是,不参与调度。

后续如果可以上到生产环境,我再写另外一篇文章来介绍一下经验。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~