descheduler整体介绍
descheduler是k8s Incubator下面的一个项目,旨在补充默认的kube-scheduler调度能力。在k8s中,pod启动之后会经过调度器调度到某个节点上,之后不会再被调度。但是,随着集群的节点和pod不断增加,就会出现下面的情况需要把pod调度到其他节点上面去运行。
- 某些节点资源使用过高
- 因为后面添加了节点affinity,taints和labels等,使得原来调度的pod与node不匹配
- 新的节点被加入到集群当中,需要在其他节点转移pod到新的 node上
deshceduler的主要功能是寻找出一些可以被调度的pod,然后把它们从原来的节点进行evicts,依赖于默认的调度器将重新生成的pod调度到其他节点上,从而起到调整集群pod分布的目的。descheduler主要包含四个策略:
- RemoveDuplicates:一个node上有由deployment,rc,rs,job管理着的pod时,evict到剩下一个pod。
- LowNodeUtilization: 集群中有资源利用不充分的node时,从资源利用率高的node中驱逐一些pod,期待默认scheduler将其调度。
- RemovePodsViolatingInterPodAntiAffinity:同一个node中若有反亲和性的pods,如果antiaffinity是在pod已经在运行中添加的,会出现这种情况。这时候可以驱逐不符合affinity的pod。
- RemovePodsViolatingNodeAffinity:pod不能满足node的affinity而集群中有其他node能够满足pod的affinity,需要驱逐pod。
desheculer的主要工作原理是使用封装好的k8s客户端client-go与k8s集群进行通信,获取集群中node和pod的情况,然后依次执行四个驱逐策略想集群发送驱逐pod的请求进行evict。下面从阅读descheduler源代码区分析descheduler的具体逻辑。
descheduler源码阅读笔记
descheduler的代码开源在github,可以下载到本地进行阅读。descheduler代码量不大,逻辑清晰,下面先展示一下descheduler项目的代码结构。
入口代码
代码主要集中在两个文件夹下面,分别是cmd和pkg,其中cmd下面是入口代码,主要是使用了一个cobra命令行程序软件包,负责读入启动程序时的参数。在/descheduler/cmd/descheduler/app/server.go里面的Run函数会跳转到pkg包下面的descheduler主函数。
// line: 59
func Run(rs *options.DeschedulerServer) error {
return descheduler.Run(rs)
}
主函数如下:
func main() {
out := os.Stdout
cmd := app.NewDeschedulerCommand(out)
cmd.AddCommand(app.NewVersionCommand())
flag.CommandLine.Parse([]string{
})
if err := cmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
cmd.Execute()
正式执行descheduler逻辑。
接下来主要分析一下pkg里面的descheduler逻辑。
deschduler主逻辑
主要的执行逻辑都在/pkg/descheduler/descheduler.go里面
// /pkg/descheduler/descheduler.go
func Run(rs *options.DeschedulerServer) error {
// 获取k8s的客户端
rsclient, err := client.CreateClient(rs.KubeconfigFile)
rs.Client = rsclient
// 从配置文件中载入配置
deschedulerPolicy, err := LoadPolicyConfig