scheudler是kubernetes中的核心组件,负责为用户声明的pod资源选择合适的node,同时保证集群资源的最大化利用,这里先介绍下资源调度系统设计里面的一些基础概念node
基础的任务资源调度一般包括三部分:web
角色类型 | 功能 |
---|---|
node | node负责具体任务的执行,同时对包汇报本身拥有的资源 |
resource manager | 汇总当前集群中全部node提供的资源,供上层的scheduler的调用获取,同时根据node汇报的任务信息来进行当前集群资源的更新 |
scheduler | 结合当前集群的资源和用户提交的任务信息,选择合适的node节点当前的资源,分配节点任务,尽量保证任务的运行 |
通用的调度框架每每还会包含一个上层的集群管理器,负责针对集群中scheduler的管理和资源分配工做,同时负责scheduler集群状态甚至resource manager的保存算法
传统的IDC集群资源利用:
在IDC环境中咱们一般但愿机器利用率可以平均,让机器保持在某个平均利用率,而后根据资源的须要预留足够的buffer, 来应对集群的资源利用高峰,毕竟采购一般都有周期,咱们既不能让机器空着,也不能让他跑满(业务没法弹性)
云环境下的资源利用:
而云环境下咱们能够按需分配,并且云厂商一般都支持秒级交付,那其实下面的这种资源利用率其实也能够
能够看到仅仅是环境的不一致,就可能会致使不一样的调度结果,全部针对集群资源利用最大化这个目标,其实会有不少的不一样api
在集群任务繁忙的时候,可能会致使集群资源部足以分配给当前集群中的全部任务,在让全部任务都可以尽快完成的同时,咱们还要保证高优先级的任务优先被完成网络
本地性是指在大数据处理中经常使用的一种机制,其核心是尽量将任务分配到包含其任务执行资源的节点上,避免数据的复制数据结构
在调度过程当中可能因为硬件、系统或者软件致使任务的不可用,一般会由须要一些高可用机制,来保证当前集群不会由于部分节点宕机而致使整个系统不可用架构
扩展机制主要是指的,系统如何如何应对业务需求的变化,提供的一种可扩展机制,在集群默认调度策略不知足业务需求时,经过扩展接口,来进行系统的扩展知足业务需求框架
Pod调度场景其实能够看作一类特殊的任务,除了上面资源调度的挑战,还有一些针对pod调度这个具体的场景(有些是共同的,这里经过pod来描述会比较清晰)ide
在kubernetes中的亲和性主要体现pod和node两种资源,主要体如今两个方面:
1.亲和性: 1)pod之间的亲和性 2)pod与node之间的亲和性
2.反亲和: 1)pod之间的反亲和性 2)pod与node之间的反亲和
简单举例:
1.pod之间的反亲和: 为了保证高可用咱们一般会将同一业务的多个节点分散在不通的数据中心和机架
2.pod与node亲和性: 好比某些须要磁盘io操做的pod,咱们能够调度到具备ssd的机器上,提升IO性能性能
多租户一般是为了进行集群资源的隔离,在业务系统中,一般会按照业务线来进行资源的隔离,同时会给业务设定对应的容量,从而避免单个业务线资源的过分使用影响整个公司的全部业务
zone一般是在业务容灾中常见的概念,经过将服务分散在多个数据中心,避免由于单个数据中心故障致使业务彻底不可用
由于以前亲和性的问题,如何在多个zone中的全部node中选择出一个合适的节点,则是一个比较大的挑战
系统资源除了cpu、内存还包括网络、磁盘io、gpu等等,针对其他资源的分配调度,kubernetes还须要提供额外的扩展机制来进行调度扩展的支持
kubernetes初期是针对pod调度场景而生,主要实际上是在线web业务,这类任务的特色大部分都是无状态的,那如何针对离线场景的去支持离线的批处理计算等任务
kubernetes是一个数据中心化存储的系统,集群中的全部数据都经过apiserver存储到etcd中,包括node节点的资源信息、节点上面的pod信息、当前集群的全部pod信息,在这里其实apiserver也充当了resource manager的角色,存储全部的集群资源和已经分配的资源
kubernetes中采用了一种list watch的机制,用于集群中其余节点从apiserver感知数据,scheduler也采用该机制,经过在感知apiserver的数据变化,同时在本地memory中构建一份cache数据(资源数据),来提供调度使用,即SchedulerCache
大多数系统的高可用机制都是经过相似zookeeper、etcd等AP系统实现,经过临时节点或者锁机制机制来实现多个节点的竞争,从而在主节点宕机时,可以快速接管, scheduler天然也是这种机制,经过apiserver底层的etcd来实现锁的竞争,而后经过apiserver的数据,就能够保证调度器的高可用
当从apiserver感知到要调度的pod的时候,scheduler会根据pod的优先级,来说其加入到内部的一个优先级队列中,后续调度的时候,会先获取优先级比较高的pod来进行优先知足调度
这里还有一个点就是若是优先调度了优先级比较低的pod,其实在后续的抢占过程当中,也会被驱逐出去
前面提到过抢占,kubernetes默认会对全部的pod来尝试进行调度,当集群资源部知足的时候,则会尝试抢占调度,经过抢占调度,为高优先级的pod来进行优先调度 其核心都是经过调度算法实现即ScheduleAlgorithm
这里的调度算法其实是一堆调度算法和调度配置的集合
scheduler extender是k8s对调度器的一种扩展机制,咱们能够定义对应的extender,在对应资源的调度的时候,k8s会检查对应的资源,若是发现须要调用外部的extender,则将当前的调度数据发送给extender,而后汇总调度数据,决定最终的调度结果
上面提到调度算法是一组调度算法和调度配置的集合,kubernetes scheduler framework是则是一个框架声明对应插件的接口,从而支持用户编写本身的plugin,来影响调度决策,我的感受这并非一种好的机制,由于要修改代码,或者经过修改kubernetes scheduler启动来进行自定义插件的加载
结合上面所说的就获得了一个最简单的架构,主要调度流程分为以下几部分:
0.经过apiserver来进行主节点选举,成功者进行调度业务流程处理
1.经过apiserver感知集群的资源数据和pod数据,更新本地schedulerCache
2.经过apiserver感知用户或者controller的pod调度请求,加入本地调度队列
3.经过调度算法来进行pod请求的调度,分配合适的node节点,此过程可能会发生抢占调度
4.将调度结果返回给apiserver,而后由kubelet组件进行后续pod的请求处理
这是一个最简单的调度流程和基础的组件模块,因此没有源码,后续这个系列会详细分析每一个关键的调度数据结构和一些有趣的调度算法的具体实现,祝我好运,good luck
k8s源码阅读电子书地址: https://www.yuque.com/baxiaoshi/tyado3