diff --git a/scheduler/Kubernetes源码学习-Scheduler-P1-调度器入口篇.md b/scheduler/Kubernetes源码学习-Scheduler-P1-调度器入口篇.md index d8992bf..068206c 100644 --- a/scheduler/Kubernetes源码学习-Scheduler-P1-调度器入口篇.md +++ b/scheduler/Kubernetes源码学习-Scheduler-P1-调度器入口篇.md @@ -56,8 +56,8 @@ matebook-x-pro:local ywq$ go run main.go # 因需要多次测试,这里所有的测试步骤就把build的步骤跳过,直接使用go run main.go进行测试 ``` **我们打开IDE来查看一下testapp的代码结构:** -![image](http://pwh8f9az4.bkt.clouddn.com/cobra1.jpg) -![image](http://pwh8f9az4.bkt.clouddn.com/cobra2.jpg) +![image](http://mycloudn.kokoerp.com/cobra1.jpg) +![image](http://mycloudn.kokoerp.com/cobra2.jpg) ``` # 现在还未创建子命令,那么来创建几个试试: @@ -90,7 +90,7 @@ add called ``` **来看看新增的子命令是怎么运行的呢?** -![image](http://pwh8f9az4.bkt.clouddn.com/cobra3.jpg) +![image](http://mycloudn.kokoerp.com/cobra3.jpg) 截图圈中部分可以看出,子命令是在init()函数里为root级添加了一个子命令,先不去管底层实现,接着往下. **测试cobra的强大简洁的flag处理** @@ -101,7 +101,7 @@ deleteCmd.PersistentFlags().StringVar(&obj,"object", "", "A function to delete a ``` 在`Run:func()`匿名函数中添加一行输出: `fmt.Println("delete obj:",cmd.Flag("object").Value)` -![image](http://pwh8f9az4.bkt.clouddn.com/cobra4.jpg) +![image](http://mycloudn.kokoerp.com/cobra4.jpg) 运行结果: @@ -112,7 +112,7 @@ delete obj: obj1 ``` 如果觉得`--`flag符号太麻烦,cobra同样支持短符号`-`flag缩写: -![image](http://pwh8f9az4.bkt.clouddn.com/cobra5.jpg) +![image](http://mycloudn.kokoerp.com/cobra5.jpg) 运行结果: @@ -132,7 +132,7 @@ add.go delete.go get.go pods.go root.go ``` 可以发现,cmd/目录下多了一个pods.go文件,我们来看看它是怎么关联上delete父级命令的,同时为它添加一行输出: -![image](http://pwh8f9az4.bkt.clouddn.com/cobra6.jpg) +![image](http://mycloudn.kokoerp.com/cobra6.jpg) 执行命令: ``` @@ -146,13 +146,13 @@ delete pods: pod1 ## 入口 通过对上方cobra的基本了解,我们不难知道,`cmd/kube-scheduler/scheduler.go`内的main()方法内部实际调用的是`cobra.Command.Run`内的匿名函数,我们可以进入`NewSchedulerCommand()`内部确认: -![image](http://pwh8f9az4.bkt.clouddn.com/main1.jpg) +![image](http://mycloudn.kokoerp.com/main1.jpg) 可以看到,调用了`Run`内部`runCommand`方法,再来看看Run方法内部需要重点关注的几个点: -![image](http://pwh8f9az4.bkt.clouddn.com/runCommand.jpg) +![image](http://mycloudn.kokoerp.com/runCommand.jpg) 其中,上方是对命令行的参数、选项校验的步骤,跳过,重点关注两个变量:`cc和stopCh`,这两个变量会作为最后调用`Run()`方法的参数,其中`stopCh`作用是作为主程序退出的信号通知其他各协程进行相关的退出操作的,另外一个cc变量非常重要,可以点击`c.Complete()`方法,查看该方法的详情: -![image](http://pwh8f9az4.bkt.clouddn.com/runCommand.jpg) +![image](http://mycloudn.kokoerp.com/runCommand.jpg) `Complete()`方法本质上返回的是一个Config结构体,该结构体内部的元素非常丰富,篇幅有限就不一一点开截图了,大家可以自行深入查看这些元素的作用,这里简单概括一下其中几个: ``` @@ -175,14 +175,14 @@ Recorder record.EventRecorder Broadcaster record.EventBroadcaster ``` 这里层级非常深,不便展示,Config这一个结构体非常重要,可以认真读一读代码。回到`cmd/kube-scheduler/app/server.go`.`runCommand`这里来,接着往下,进入其最后return调用的`Run()`函数中,函数中的前部分都是启动scheduler相关的组件,如event broadcaster、informers、healthz server、metric server等,重点看图中红框圈出的`sched.Run()`,这才是scheduler主程序的调用运行函数: -![image](http://pwh8f9az4.bkt.clouddn.com/Run.jpg) +![image](http://mycloudn.kokoerp.com/Run.jpg) 进入`sched.Run()`: -![image](http://pwh8f9az4.bkt.clouddn.com/scheRun.jpg) +![image](http://mycloudn.kokoerp.com/scheRun.jpg) `wait.Until`这个调用的逻辑是,直到收到stop信号才终止,在此之前循环运行`sched.scheduleOne`。代码走到这里,终于找到启动入口最内部的主体啦: -![](http://pwh8f9az4.bkt.clouddn.com/image-20190827163439895.png) +![](http://mycloudn.kokoerp.com/image-20190827163439895.png) `sched.scheduleOne`这个函数有代码点长,整体的功能可以概括为: diff --git a/scheduler/Kubernetes源码学习-Scheduler-P3-Node筛选算法.md b/scheduler/Kubernetes源码学习-Scheduler-P3-Node筛选算法.md index 60c3e67..072cd63 100644 --- a/scheduler/Kubernetes源码学习-Scheduler-P3-Node筛选算法.md +++ b/scheduler/Kubernetes源码学习-Scheduler-P3-Node筛选算法.md @@ -145,7 +145,7 @@ ParallelizeUntil()的这种实现方式,可以很好地将并发实现和具 `pkg/scheduler/core/generic_scheduler.go:460 --> pkg/scheduler/internal/cache/node_tree.go:161` -![](http://pwh8f9az4.bkt.clouddn.com/zone.jpg) +![](http://mycloudn.kokoerp.com/zone.jpg) 可以看到,这里有一个zone的逻辑层级,这个层级仿佛没有见过,google了一番才了解了这个颇为冷门的功能:这是一个轻量级的支持集群联邦特性的实现,单个cluster可以属于多个zone,但这个功能目前只有GCE和AWS支持,且绝大多数的使用场景也用不到,可以说是颇为冷门。默认情况下,cluster只属于一个zone,可以理解为cluster和zone是同层级,因此后面见到有关zone相关的层级,我们直接越过它。有兴趣的朋友可以了解一下zone的概念: @@ -231,7 +231,7 @@ func podFitsOnNode( 有了以上理解,我们接着看代码,图中已注释: -![](http://pwh8f9az4.bkt.clouddn.com/podFitsOnNode.jpg) +![](http://mycloudn.kokoerp.com/podFitsOnNode.jpg) 图中`pkg/scheduler/core/generic_scheduler.go:608`位置正式开始了逐个计算筛选算法,那么筛选方法、筛选方法顺序在哪里呢?在上一篇[P2-框架篇]([https://github.com/yinwenqin/kubeSourceCodeNote/blob/master/scheduler/P2-%E8%B0%83%E5%BA%A6%E5%99%A8%E6%A1%86%E6%9E%B6.md](https://github.com/yinwenqin/kubeSourceCodeNote/blob/master/scheduler/P2-调度器框架.md))中已经有讲过,默认调度算法都在`pkg/scheduler/algorithm/`路径下,我们接着往下看. @@ -260,7 +260,7 @@ var ( [链接](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/predicates-ordering.md) -![](http://pwh8f9az4.bkt.clouddn.com/predicates.jpg) +![](http://mycloudn.kokoerp.com/predicates.jpg) #### 筛选key @@ -385,4 +385,4 @@ func CheckNodeMemoryPressurePredicate(pod *v1.Pod, meta PredicateMetadata, nodeI -本篇调度器筛选算法篇到此结束,下一篇将学习调度器优先级排序的算法详情内容 \ No newline at end of file +本篇调度器筛选算法篇到此结束,下一篇将学习调度器优先级排序的算法详情内容 diff --git a/scheduler/Kubernetes源码学习-Scheduler-P4-Node优先级算法.md b/scheduler/Kubernetes源码学习-Scheduler-P4-Node优先级算法.md index e4e7b94..55fa53f 100644 --- a/scheduler/Kubernetes源码学习-Scheduler-P4-Node优先级算法.md +++ b/scheduler/Kubernetes源码学习-Scheduler-P4-Node优先级算法.md @@ -18,7 +18,7 @@ Tips: 本篇篇幅较长,因调度优选算法较为复杂,但请耐心结 同上一篇,回到`pkg/scheduler/core/generic_scheduler.go`中的`Schedule()`函数,`pkg/scheduler/core/generic_scheduler.go:184`: -![](http://pwh8f9az4.bkt.clouddn.com/20190822165920.png) +![](http://mycloudn.kokoerp.com/20190822165920.png) 截图中有几处标注,metric相关的几行,是收集metric信息,用以提供给prometheus使用的,kubernetes的几个核心组件都有这个功能,以后如果读prometheus的源码,这个单独拎出来再讲。直接进入优先级函数`PrioritizeNodes()`内部`pkg/scheduler/core/generic_scheduler.go:215` @@ -201,7 +201,7 @@ func defaultPriorities() sets.String { 在注册的每一个计算维度,都有专属的维度描述关键字,即factory方法的第一个参数(str类型)。不难发现,这里的每一个关键字,`pkg/scheduler/algorithm/priorities`目录内都有与其对应的文件,图中圈出了几个例子(灵魂画笔请原谅): -![](http://pwh8f9az4.bkt.clouddn.com/image-20190821171031395.png) +![](http://mycloudn.kokoerp.com/image-20190821171031395.png) 显而易见,维度计算的内容就在这些文件中,可以自行通过编辑器的跳转功能逐级查看进行验证. @@ -239,7 +239,7 @@ func CalculateNodePreferAvoidPodsPriorityMap(pod *v1.Pod, meta interface{}, node 这也印证了前面说的当前仅剩pod亲和性这一个维度在使用传统的Function,虽然已经被DEPRECATED掉了,传统的Function是直接计算出结果,Map-Reduce是将这个过程解耦拆成了两个步骤,且我们可以看到所有的factory函数,很多形参`reduceFunction`接收到的实参实际是是`nil`: -![](http://pwh8f9az4.bkt.clouddn.com/image-20190822111624614.png) +![](http://mycloudn.kokoerp.com/image-20190822111624614.png) 这就说明这些维度的计算工作在map函数里面已经执行完成了,不需要再执行reduce函数了。因此,传统的Function的计算过程同样值得参考,那么首先就来看看`InterPodAffinityPriority`维度是怎么计算的吧! @@ -634,4 +634,4 @@ fScore = float64(schedulerapi.MaxPriority) * ((pm.counts[node.Name] - minCount) 优先级算法相对而言比predicate断言算法要复杂一些,并且在当前版本的维度计算中存在传统Function函数与Map-Reduce风格函数混用的现象,一定程度上提高了阅读的难度,但相信仔细重复阅读代码,还是不难理解的,毕竟数据量还未到达大数据的级别,只是利用了其映射归纳的思想,解耦的同时提高一定的并发性能。 -下一篇讲什么呢?我再研究研究,have fun! \ No newline at end of file +下一篇讲什么呢?我再研究研究,have fun!