为了深入学习 kube-scheduler,本系从源码和实战角度深度学 习kube-scheduler,该系列一共分6篇文章,如下:
- kube-scheduler 整体架构
- 初始化一个 scheduler
- 一个 Pod 是如何被调度的
- 如何开发一个属于自己的scheduler插件
- 开发一个 prefilter 扩展点的插件
- 开发一个 socre 扩展点的插件
上一篇,我们说了 kube-scheduler 的整体架构,是从整体的架构方面来考虑的,本文我们说说 kube-scheduler 是如何初始化出来的,kube-scheduler 里面都有些什么东西。
因为 kube-scheduler 源码内容比较多,对于那些不是关键的东西,就忽略不做讨论。
Scheduler之Profiles
下面我们先看下 Scheduler 的结构
type Scheduler struct {
Cache internalcache.Cache
Extenders []framework.Extender
NextPod func() *framework.QueuedPodInfo
FailureHandler FailureHandlerFn
SchedulePod func(ctx context.Context, fwk framework.Framework, state *framework.CycleState, pod *v1.Pod) (ScheduleResult, error)
StopEverything <-chan struct{}
SchedulingQueue internalqueue.SchedulingQueue
Profiles profile.Map
client clientset.Interface
nodeInfoSnapshot *internalcache.Snapshot
percentageOfNodesToScore int32
nextStartNodeIndex int
}
上一篇我们说过,为一个 Pod 选择一个 Node 是按照固定顺序运行扩展点的;在扩展点内,是按照插件注册的顺序运行插件,如下图
上面的这些扩展点在 kube-scheduler 中是固定的,而且也不支持增加扩展点(实际上有这些扩展点已经足够了),而且扩展点顺序也是固定执行的。
下图是插件(以preFilter为例)运行的顺序,扩展点内的插件,你既可以调整插件的执行顺序(实际很少会修改默认的插件执行顺序),可以关闭某个内置插件,还可以增加自己开发的插件。
那么这些插件是怎么注册的,注册在哪里呢,自己开发的插件又是怎么加进去的呢?
我们来看下 Scheduler 里面最重要的一个成员:Profiles profile.Map
// 路径:pkg/scheduler/profile/profile.go
// Map holds frameworks indexed by scheduler name.
type Map map[string]framework.Framework
Profiles 是一个 key 为 scheduler name,value 是 framework.Framework 的map,表示根据 scheduler name 来获取 framework.Framework 类型的值,所以可以有多个scheduler。或许你在使用 k8s 的时候没有关注过 pod 或 deploment 里面的 scheduler,因为你没有指定的话,k8s 就会自动设置为默认的调度器,下图是 deployment 中未指定 schedulerName 被设置了默认调度器的一个deployment
](https://i-blog.csdnimg.cn/blog_migrate/9e662dad16fdfda6d82e8b91dee99af6.png)
假设现在我想要使用自己开发的一个名叫 my-scheduler-1 的调度器,这个调度器在 preFilter 扩展点中增加了 zoneLabel 插件,怎么做?
使用 kubeadm 部署的 k8s 集群,会在 /etc/kubernetes/manifests 目录下创建 kube-scheduler.yaml 文件,kubelet 会根据这个文件自动拉起来一个静态 Pod,一个 kube-scheduler pod就被创建了,而且这个 kube-scheduler 运行的参数是直接在命令行上指定的。
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-scheduler
tier: control-plane
name: kube-scheduler
namespace: kube-system
spec:
containers:
- command:
- kube-scheduler
- --address=0.0.0.0
- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
- --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
- --bind-address=127.0.0.1
- --kubeconfig=/etc/kubernetes/scheduler.conf
- --leader-elect=true
image: k8s.gcr.io/kube-scheduler:v1.16.8
....
其实 kube-scheduler 运行的时候可以指定配置文件,而不直接把参数写在启动命令上,如下形式。
./kube-scheduler --config /etc/kube-scheduler.conf
于是乎,我们就可以在配置文件中配置我们调度器的插件了
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfi