一、predicate注册过程

今天我们来聊聊predicate函数是怎么被注册进去的,也就是要执行的一堆predicate是怎么成为“选中的孩子”。 
代码位置:pkg/scheduler/factory/plugins.go:111
这个函数注册一个predicate函数,返回predicate名。
 
第二个参数:
type FitPredicate func(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error)
 
这个函数(RegisterFitPredicate)的被调用场景如下,第一个参数是一个字符串常量,第二个参数是一个函数类型
RegisterFitPredicate的2个参数其实长这个样子,如下:
 
 
RegisterFitPredicate中调用的是RegisterFitPredicateFactory完成注册逻辑,RegisterFitPredicateFactory定义如下:
这个函数的参数是:
  • name string
  • predicateFactory FitPredicateFactory
返回值是:
  • string
 
其中FitPredicateFactory是一个函数类型,签名是:
func(PluginFactoryArgs) algorithm.FitPredicate
 
PluginFactoryArgs是一堆factory函数:
 
RegisterFitPredicateFactory的第二个参数比较复杂,是一个函数类型,这个类型的参数在RegisterFitPredicate中的实参用了:
func(PluginFactoryArgs) algorithm.FitPredicate { return predicate }
这个地方相比上面的类型定义只多了“{ return predicate }”,也就是加了一个函数体,函数体里只有一个return,好理解,也就是一个匿名函数。
 
RegisterFitPredicateFactory中除了锁操作外只有2行:
  • 第一行:正则匹配判断name是否合法,规则是:
    "^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])$"
  • 第二行:fitPredicateMap的类型是map[string]FitPredicateFactory,一个包级变量;也就是把predicate的名字当做key,把一个以PluginFactoryArgs为参数,algorithm.FitPredicate为返回值的函数当做value.
 
也就是说RegisterFitPredicateFactory函数是把predicate函数注册到包(factory)级别的fitPredicateMap中;换言之开头提到的RegisterFitPredicate函数最终是把predicate注册到factory.fitPredicateMap
 
到这里可能还不太理解PluginFactoryArgs的作用,但是我们关注到RegisterFitPredicate的输入值是predicate的名字和具体的实现函数,结果是fitPredicateMap这个map里加了一个元素,key是predicate名,value是一个FitPredicateFactory类型数据,这个类型是一个func,这个func定义是:func(PluginFactoryArgs) algorithm.FitPredicate,也就是给一个PluginFactoryArgs就可以返回一个具体的predicate function.后面我们对照具体使用PluginFactoryArgs的地方再来理解它的实际含义。
 

二、ApplyFeatureGates入口

cmd/kube-scheduler/app/server.go:297 Run()这个函数中有这样一步:
这个Run是在最开头的地方被调用的,如下位置:
ApplyFeatureGates函数的定义如下:
这里调用的ApplyFeatureGates的位置是:
pkg/scheduler/algorithmprovider/defaults/defaults.go:180
这个go文件在defaults包下,这个包内包含这些东西:
这里的函数基本都是小写字母开头的,换言之都是包内访问的。另外有一个init()函数,这里的逻辑在调用ApplyFeatureGates()函数之前执行。所以下面看一下defaults包。
 

三、defaults包

pkg\scheduler\algorithmprovider\defaults\defaults.go中的init()函数
init()函数前面调用了registerAlgorithmProvider函数,参数是defaultPredicates()和defaultPriorities(),明显是注册默认的predicates和priorities.我们先关注predicate默认有哪些
(pkg/scheduler/algorithmprovider/defaults/defaults.go:112):
这里用紫色的常量名来统计有12个:
  1. NoVolumeZoneConflictPred
  2. MaxEBSVolumeCountPred
  3. MaxGCEPDVolumeCountPred
  4. MaxAzureDiskVolumeCountPred
  5. MatchInterPodAffinityPred
  6. NoDiskConflictPred
  7. GeneralPred
  8. CheckNodeMemoryPressurePred
  9. CheckNodeDiskPressurePred
  10. CheckNodeConditionPred
  11. PodToleratesNodeTaintsPred
  12. CheckVolumeBindingPred
init()函数中接着注册了4个predicate(name->func):
  1. PodFitsHostPorts -> predicates.PodFitsHostPorts
  2. PodFitsResources -> predicates.PodFitsResources
  3. HostName -> predicates.PodFitsHost
  4. MatchNodeSelector -> predicates.PodMatchNodeSelector
然后注册一个获取等价pod的函数:
函数名很直观:RegisterGetEquivalencePodFunction;这个函数的参数是一个匿名函数,匿名函数的参数前面见过很多次了,先关注一下返回值是什么:algorithm.GetEquivalencePodFunc;这个类型其实也是一个函数类型,签名是:func(pod *v1.Pod) interface{},也就是以pod信息为参数,返回任意类型。接着看一下前面这个匿名函数的return部分写的是什么:predicates.NewEquivalencePodGenerator(args.PVCInfo)
这里的g是这样定义的:
return部分调用了一个方法,这个方法长这个样子:
这个方法返回一个EquivalencePod,也就是等价pod,定义如下:
这个OwnerReference包含判断一个资源身份所需要的足够的信息:
RegisterGetEquivalencePodFunction函数在注册的时候把传进来的匿名函数注册到了哪里呢?
这里的getEquivalencePodFuncFactory明显又是一个包级变量,定义位置是:pkg/scheduler/factory/plugins.go:95.
所以总结下来就是说init()中的factory.RegisterGetEquivalencePodFunction函数把一个获取等价pod的函数注册到了factory包的包级变量getEquivalencePodFuncFactory中
再看defaults.go中唯一一个可导出函数ApplyFeatureGates;
这个函数在TaintNodesByCondition特性打开的情况下调整了几个predicate,特性的定义跟进去可以看到(pkg/features/kube_features.go:140):
这里的Feature类型其实很简单,跟一下可以看到这一行定义:type Feature string.可以发现这里定义了很多的alpha或者beta的特性,明显这里是做了开关,各种未稳定发布的特性可以选择性放出来。其实在scheduler组件启动的时候有一个命令行参数是:--feature-gates=...,TaintNodesByCondition=true,也就是可以通过这种方式打开一个feature.特性开关的事情后面再详细介绍,关于predicate算法注册的内容今天就讲到这里!

 

105 - kube-scheduler源码分析 - predicate算法注册的更多相关文章

  1. scheduler源码分析——preempt抢占

    前言 之前探讨scheduler的调度流程时,提及过preempt抢占机制,它发生在预选调度失败的时候,当时由于篇幅限制就没有展开细说. 回顾一下抢占流程的主要逻辑在DefaultPreemption ...

  2. scheduler源码分析——调度流程

    前言 当api-server处理完一个pod的创建请求后,此时可以通过kubectl把pod get出来,但是pod的状态是Pending.在这个Pod能运行在节点上之前,它还需要经过schedule ...

  3. Go合集,gRPC源码分析,算法合集

    年初时,朋友圈见到的最多的就是新的一年新的FlAG,年末时朋友圈最多的也是xxxx就要过去了,你的FLAG实现了吗? 这个公众号2016就已经创建了,但截至今年之前从来没发表过文章,现在想想以前很忙, ...

  4. 104 - kube-scheduler源码分析 - predicate整体流程

    (注:从微信公众:CloudGeek复制过来,格式略微错乱,更好阅读体验请移步公众号,二维码在文末) 今天我们来跟一下predicates的整个过程:predicate这个词应该是“断言.断定”的意思 ...

  5. Hadoop学习之--Capaycity Scheduler源码分析

    Capacity Scheduler调度策略当一个新的job是否允许添加到队列中进行初始化,判断当前队列和用户是否已经达到了初始化数目的上限,下面就从代码层面详细介绍整个的判断逻辑.Capaycity ...

  6. scrapy-redis(调度器Scheduler源码分析)

    settings里面的配置:'''当下面配置了这个(scrapy-redis)时候,下面的调度器已经配置在scrapy-redis里面了'''##########连接配置######## REDIS_ ...

  7. Spring Cloud Eureka源码分析之服务注册的流程与数据存储设计!

    Spring Cloud是一个生态,它提供了一套标准,这套标准可以通过不同的组件来实现,其中就包含服务注册/发现.熔断.负载均衡等,在spring-cloud-common这个包中,org.sprin ...

  8. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  9. apiserver源码分析——启动流程

    前言 apiserver是k8s控制面的一个组件,在众多组件中唯一一个对接etcd,对外暴露http服务的形式为k8s中各种资源提供增删改查等服务.它是RESTful风格,每个资源的URI都会形如 / ...

随机推荐

  1. 配置(迁移)Laravel的注意事项

    1.如果Laravel是在Linux下运行,如果权限不足,会报错 2.如果是从git上clone下来的项目,需要安装composer,切到项目根目录下 composer install compose ...

  2. CVE-2018-8120 Microsoft Windows提权漏洞 Exp

    CVE-2018-8120 Windows LPE exploit Supports both x32 and x64. Tested on: Win7 x32, Win7 x64, Win2008 ...

  3. 深度学习之循环神经网络(RNN)

    循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络,适合用于处理视频.语音.文本等与时序相关的问题.在循环神经网络中,神经元不但可以接收其他神经元 ...

  4. 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(三)

    资料库的创建.体系结构的创建.模型反向工程都已经完成了,下面就是创建以及执行接口来完成工作了. 浏览前两节请点击: [ODI]| 数据ETL:从零开始使用Oracle ODI完成数据集成(一) [OD ...

  5. MySQL - 扩展性 2 扩展策略:氪金氪脑任君选

    如果将应用的所有数据简单地放在一台 MySQL 服务器实例上,就不用谈什么扩展性了.但是业务能稳定持续的增长,那么应用肯定会碰到性能瓶颈. 对于很多类型的应用而言,购买更高性能的机器能解决一大部分性能 ...

  6. 我不是bug神(JVM问题排查)

    Story background 回望2018年12月,这也许是程序员们日夜不得安宁的日子,皆因各种前线的系统使用者都需要冲业绩等原因,往往在这个时候会向系统同时写入海量的数据,当我们的应用或者数据库 ...

  7. Python3|ddt|unittest|浅议数据驱动测试

    目录 1.DDT简介 2.data装饰器 3.unpack装饰器 4.file_data装饰器 5.总结 1.DDT简介 Data-Driven Tests(DDT)即数据驱动测试.它允许您通过不同的 ...

  8. 19条MySQL优化准则

    1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...

  9. .Net Core ORM选择之路,哪个才适合你

    因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别的慢,导致系统体验比较差好多都改写Sql实现. 所以我 ...

  10. C#编写扫雷游戏

    翻看了下以前大学学习的一些小项目,突然发现有个项目比较有意思,觉得有必要把它分享出来.当然现在看来,里面有很多的不足之处,但因博主现在已经工作,没有时间再去优化.这个项目就是利用C#编写一个Windo ...