kube-scheduler的代码逻辑和二次开发
1.9中,kube-scheduler仍然是作为一个“plugin”放在k8s 代码中,在k8s根目录下的plugin目录中,cmd/kube-scheduler目录是其编译入口,pkg/scheduler目录是其主要核心代码。如图:
在即将发布的1.10中,社区将kube-scheduler从plugin中移出,嵌入到与api-server、kubelet等组件平级的目录。也即根目录下的cmd、pkg目录:
调度器的算法是如何生效的
调度器二进制启动
调度器可以在启动时指定其算法的来源。算法来源有三种:a)本地policy文件;b)policy configMap;c)指定提供者。
对象*scheduler.Config
记录了算法来源,当启动参数中policy相关参数不为空时,会从相应的文件或者configMap中读取调度策略;否则检查algorithm-provider
参数,这个参数会列出当前可用的provider,如果没有明确指定,那么代码将启动默认的provider:default
从policy读取的调度策略,其内容是一个policy
结构
type Policy struct { metav1.TypeMeta // Holds the information to configure the fit predicate functions Predicates []PredicatePolicy // Holds the information to configure the priority functions Priorities []PriorityPolicy // Holds the information to communicate with the extender(s) ExtenderConfigs []ExtenderConfig // RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule // corresponding to every RequiredDuringScheduling affinity rule. // HardPodAffinitySymmetricWeight represents the weight of implicit PreferredDuringScheduling affinity rule, in the range 1-100. HardPodAffinitySymmetricWeight int32 }
代码会直接根据policy
的内容,调用CreateFromKeys
方法去构建最终的scheduler
当没有指定policy时,如果没有指定provider,最后会执行下面这个函数
// Create creates a scheduler with the default algorithm provider. func (f *configFactory) Create() (*scheduler.Config, error) { return f.CreateFromProvider(DefaultProvider) }
随后也会调用CreateFromKeys
方法构建最终的genericScheduler
调度器算法注入
上面的过程中,会最终都调用到func (f *configFactory) CreateFromKeys
。 这个函数将参数中的predicate算法、priority算法等注入到调用链中,这个调用链中的函数,会在每次调度pod时被调用。两个调用链分别是genericScheduler
结构中的:
type genericScheduler struct { ... predicates map[string]algorithm.FitPredicate ... prioritizers []algorithm.PriorityConfig ... }
当通过policy启动时,CreateFromKeys
方法的参数中的算法都记录到了policy
对象中的成员变量里。而如果通过指定provider启动,参数中的算法都来自provider 的init
方法。
我们通过阅读provider的init
方法,以及init过程中引用到的plugins.go
的一些方法,就能知道大概的流程是:
1.调度器的algorithmprovider
目录下存放了一个defaults
provider,以及一个plugins.go
的文件,plugins.go
提供了provider登记需要的一些方法。
2.plugins.go
中维护了一个全局的map:algorithmProviderMap
, 这个map的key即provider的名字,value是一个结构,维护了两个string集合,用于记录该provider需要的prodicate算法名和priority算法名:
type AlgorithmProviderConfig struct {
FitPredicateKeys sets.String PriorityFunctionKeys sets.String
}
3.provider的init
方法中调用factory.RegisterAlgorithmProvider
方法,向上文的map中登记自己。登记时会提供自己本身包含的两类算法的集合。可参考defaults/defaults.go
中的:
registerAlgorithmProvider(defaultPredicates(), defaultPriorities())
defaultPredicates()
、defaultPriorities()
两个函数返回的就是两个集合,只有集合中的字符串对应的算法才会注入到genericScheduler
,从而被调用。而这里字符串和真实算法function的映射关系,分别记录在两个全局map:
fitPredicateMap
和priorityFunctionMap
中,defaults.go
中 调用的RegisterFitPredicate
、RegisterMandatoryFitPredicate
等许多方法均会将算法名和算法方法的映射记录到map中。
这里注意到,并不是所有的算法都会登记到集合中的,这里PodFitsPorts
、PodFitsHostPorts
、PodFitsResources
等算法只是记录到map中,并没有登记到set中,但是也被调用了,这是因为这些算法都属于GeneralPredicates
算法,在GeneralPredicates
算法中被调用。而代码中下文我们会看到在default provider 中登记了GeneralPredicates
算法
总结下来就是:要将predicate算法或prioirity算法的映射关系注册到全局map中,然后将算法名登记到provider中,再将provider登记到全局map中,在启动scheduler时指定provider的name,就可以使用相应的provider名下登记的算法来构造genericScheduler
。
如何增加算法
上文中提及的plugins.go
中, 还提供了一些额外的方法,比如:InsertPredicateKeyToAlgoProvider
方法,可以将某个算法登记到指定的provider中。
因此,我们只要在init时将自定义的算法先注册到全局map中:
func init() { factory.RegisterFitPredicate("PodFitsNeteaseResources", predicates.PodFitsNeteaseResources)) }
然后在defaults/defaults.go
的init方法尾部,调用InsertPredicateKeyToAlgoProvider
将带有自定义算法的名字的set加入default provider即可:
factory.InsertPredicateKeyToAlgoProvider(factory.DefaultProvider, sets.NewString("PodFitsNeteaseResources"))
上述是一个比较规范的注册方式,也有投机取巧的方式,比如在default provider 的func defaultPredicates()
方法尾部增加一行:
factory.RegisterFitPredicate("PodFitsNeteaseResources", predicates.PodFitsNeteaseResources))
本文转自SegmentFault- kube-scheduler的代码逻辑和二次开发 低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
使用 Prometheus 监控 Kubernetes 应用
我们和大家介绍了Prometheus的数据指标是通过一个公开的 HTTP(S) 数据接口获取到的,我们不需要单独安装监控的 agent,只需要暴露一个 metrics 接口,Prometheus 就会定期去拉取数据;对于一些普通的 HTTP 服务,我们完全可以直接重用这个服务,添加一个/metrics接口暴露给 Prometheus;而且获取到的指标数据格式是非常易懂的,不需要太高的学习成本。 现在很多服务从一开始就内置了一个/metrics接口,比如 Kubernetes 的各个组件、istio 服务网格都直接提供了数据指标接口。有一些服务即使没有原生集成该接口,也完全可以使用一些 exporter 来获取到指标数据,比如 mysqld_exporter、node_exporter,这些 exporter 就有点类似于传统监控服务中的 agent,作为一直服务存在,用来收集目标服务的指标 数据然后直接暴露给 Prometheus。 普通应用监控 前面我们已经和大家学习了 ingress 的使用,我们采用的是Traefik作为我们的 ingress-controller,是我们 Kub...
- 下一篇
Kubernetes助力Spark大数据分析
Kubernetes 作为一个广受欢迎的开源容器协调系统, 是Google于2014年酝酿的项目。从Google趋势上看到,Kubernetes自2014年以来热度一路飙升,短短几年时间就已超越了大数据分析领域的长老Hadoop。本公众号之前的文章(Kubernetes核心组件解析)也对Kubernetes的几个组件做了一些详细的剖析,本文就带领大家一起看看Kubernetes和Spark碰到一起会擦出什么样的火花。 Spark2.3.0之前的版本只原生支持Standalone、YARN和Mesos三种部署模式,也就是说要迁移Spark2.3.0之前的Spark到Kuberbetes上,还得准备一层Standalone、YARN或者Mesos环境,不过Spark2.3.0已经引入了对Kubernetes的原生支持。 Spark2.3.0可以将编写好的数据处理程序直接通过spark-submit提交到Kubernetes集群,通过创建一个Drive Pod和一系列Executor Pods,然后共同协调完成计算任务,整体过程的官方示意图如下。 当我们通过spark-submit将Spar...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 设置Eclipse缩进为4个空格,增强代码规范
- Mario游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8