入口函数-main
scheduler的源码主要存放在两个文件夹下:
/cmd/kube-scheduler/,是scheduler的入口函数,文件结构如下:
kube-scheduler
├── app # 该目录下包含运行scheduler时所需要的配置对象和参数
│ ├── BUILD
│ ├── config # 包含配置对象及上下文内容
│ │ ├── BUILD
│ │ └── config.go
│ ├── options # 包含scheduler运行时需要的参数
│ │ ├── BUILD
│ │ ├── configfile.go
│ │ ├── deprecated.go
│ │ ├── deprecated_test.go
│ │ ├── insecure_serving.go
│ │ ├── insecure_serving_test.go
│ │ ├── options.go
│ │ └── options_test.go
│ ├── server.go # 读取默认配置文件,并初始化
│ └── testing
│ ├── BUILD
│ └── testserver.go
├── BUILD
├── OWNERS
└── scheduler.go # main入口函数1. main 入口函数
代码在
/cmd/kube-scheduler/scheduler.go
这里使用命令行框架cobra,创建scheduler的命令对象并对命令参数进行校验。 scheduler组件代码通过cobra生成根命令和子命令来执行命令,使用 cmd.Flags()设置命令参数,通过调用 command.Execute()检验命令参数并执行。有关cobra的更多信息,请参阅cobra。
核心代码:
1.1 NewSchedulerCommand()
代码在
/cmd/kube-scheduler/app/server.go
NewSchedulerCommand用来初始化scheduler配置并创建SchedulerCommand对象
核心代码
1.1.1 NewOptions
代码在
/cmd/kube-scheduler/app/options/options.go
NewOptions用来配置SchedulerServer需要的参数和配置,核心参数为KubeSchedulerConfiguration结构体(代码在/pkg/scheduler/apis/config/types.go )
NewOptions的代码:
在第3行中的newDefaultComponentConfig()点进去就会发现调用的是KubeSchedulerConfiguration结构体
1.1.2 runCommand
代码在
/cmd/kube-scheduler/app/server.go
代码如下:
第10行,errs := opts.Validate()校验标题1.1.1中提到的options参数
代码如下:
第26行,c, err := opts.Config()初始化scheduler的config对象
config的具体代码如下:
其中主要执行以下操作:
第15行:构建kube clients:client、leaderElectionClient、eventClient
第20行:创建event broadcaster
第24行:设置leader election(如果开启),用来对多个scheduler进行选举
第33行:创建informer对象,主要包括
NewSharedInformerFactory和NewPodInformer函数
第36行,algorithmprovider.ApplyFeatureGates()提供默认的算法,后面详细介绍
第45行和第46行:
由WithCancel()函数返回的ctx是context.Background()的子context,之后在协程中select,如果stopCh可以读取,则调用cancel()函数。这个cancel()函数在WithCancel()中返回,作用是把context所有的children关闭并移除。
WithCancel()函数的代码:
其中:第10行调用cancel()函数,具体代码如下
第48行:
return Run(ctx, cc, registryOptions...)调用了Run函数(启动程序)接着此
Run函数调用了sched.Run(ctx)(在下一节代码的106行)sched.Run(ctx)这个函数会不停的在协程中运行schedulerOne,对pod执行一轮一轮的调度,直到接收到stopChannel。与此同时,用ctx.Done()阻塞住run的运行,直到ctx.Done()可以读取,run才会返回。一旦run()结束,调度器也停止运作。
这3个小步骤是scheduler源码中主要函数的调用流程,下面对 Run 函数详细介绍
2. Run
代码在
/cmd/kube-scheduler/app/server.go
在scheduler调度逻辑开始之前,Run函数将与scheduler相关的配置先运行起来
具体代码如下:
主要功能如下:
运行event broadcaster、healthz checks、healthz server、metrics server(根据config构建一个metrics server)
创建scheduler结构体
启动所有的informer,并在调度前等待etcd中的资源数据同步到本地的store中
如果 leader election开启,并有多个scheduler,则进行选举,直到选举结束或退出(一般系统默认scheduler:default-scheduler)
运行
sched.Run函数,执行scheduler的调度逻辑
核心源码介绍:
2.1 outOfTreeRegistry
第6行,创建Registry(注册表),其中包含所有可用的plugins,并控制这些plugin的启动和初始化。这里的Registry相当于一个注册中心,只有在Registry中注册了的plugins(策略),才能在之后的scheduler调度逻辑中启动并生效。
2.1.1 Registry
代码在
/pkg/scheduler/framework/v1alpha1/registry.go
代码如下:
注释讲解很清晰,不再赘述。
2.2 scheduler.New
第22行,创建scheduler结构体,其中包含scheduler调度逻辑执行过程中需要的所有参数和配置。
其中:
第3行,
cc.InformerFactory调用的是SharedInformerFactory接口:Shared 指的是在多个 Informer 中共享一个本地 cache。第4行,
cc.PodInformer调用的是PodInformer接口:基于SharedInformer的监听pod,并根据index来管理pod(当事件类型为add时,将其保存到本地缓存store中,并创建索引;当事件类型为delete时,则在本地缓存中删除此对象)第5行,
cc.Recorder调用的是EventRecorder接口:用来record events第6行,
ctx.Done()调用的是Context接口:使用一个 Done channel从第7行开始到最后,调用的是
cc.ComponentConfig中的参数,即是KubeSchedulerConfiguration结构体:用来配置scheduler
2.3 InformerFactory.Start
第80行,启动所有informers,包括PodInformer、InformerFactory,主要涉及到informer,请参阅informer机制
2.4 WaitForCacheSync
第84行,在调度逻辑执行前,需等到所有的caches同步
在这一步,涉及到reflector(反射器)、apiserver、etcd、store等的关系,一并在informer机制中讲解
2.5 sched.Run
第106行,等待cache同步完成后,开始执行调度逻辑。
Run函数的具体代码如下:
代码在
/pkg/scheduler/scheduler.go
以上是从入口函数开始,到执行schedulerOne逻辑之前的源码分析,sched.Run的源码分析在下一节。
Last updated
Was this helpful?