k8s的调度器架构和策略

调度器功能

默认调度器的主要职责,就是为一个新创建出来的Pod寻找一个最合适的节点(Node)

调度器对一个 Pod 调度成功,实际上就是将它的 spec.nodeName 字段填上调度结果的节点名字

预选节点

从集群所有的节点中,根据调度算法挑选出所有可以运行该 Pod 的节点默认调度器会首先调用一组叫作 Predicate 的调度算法,来检查每个Node

优选节点

从预选的结果中,再根据调度算法挑选一个最符合条件的节点作为最终结果.再调用一组叫作 Priority 的调度算法,来给上一步得到的结果里的每个Node打分.最终的调度结果,就是得分最高的那个Node

调度器实现机制

调度器实现的核心就是由两个相互独立运行的控制循环

第一个控制循环,我们可以称之为Informer Path.当一个待调度Pod(它的nodeName字段是空的)被创建出来之后,调度器就会通过Pod Informer的Handler,将这个待调度Pod添加进调度队列.Kubernetes 的调度队列是一个 PriorityQueue(优先级队列)

第二个控制循环,是调度器负责Pod调度的主循环,我们可以称之为 Scheduling Path.scheduling Path的主要逻辑,就是不断地从调度队列里出队一个Pod.然后,调用 Predicates 算法进行“过滤”.这一步“过滤”得到的一组 Node,就是所有可以运行这个 Pod 的宿主机列表.当然Predicates算法需要的Node信息,都是从Scheduler Cache 里直接拿到的,这是调度器保证算法执行效率的主要手段之一.接下来,调度器就会再调用 Priorities 算法为上述列表里的 Node 打分,分数从0到10.得分最高的 Node,就会作为这次调度的结果.

Kubernetes 的默认调度器还要负责对调度器缓存(即:scheduler cache)进行更新.事实上Kubernetes 调度部分进行性能优化的一个最根本原则,就是尽最大可能将集群信息 Cache 化,以便从根本上提高Predicate和 Priority调度算法的执行效率

为了不在关键调度路径里远程访问APIServer,Kubernetes的默认调度器在Bind阶段,只会更新Scheduler Cache里的Pod和Node的信息.这种基于“乐观”假设的 API 对象更新方式,在Kubernetes里被称作Assume

默认调度器可扩展性设计

默认调度器的可扩展机制,在 Kubernetes里面叫作 Scheduler Framework.这个设计的主要目的,就是在调度器生命周期的各个关键点上,为用户暴露出可以进行扩展和实现的接口,从而实现由用户自定义调度器的能力

每一个绿色的箭头都是一个可以插入自定义逻辑的接口.比如,上面的 Queue 部分,就意味着你可以在这一部分提供一个自己的调度队列的实现,从而控制每个Pod 开始被调度(出队)的时机

Predicates部分,则意味着你可以提供自己的过滤算法实现,根据自己的需求,来决定选择哪些机器

上述这些可插拔式逻辑,都是标准的Go语言插件机制(Go plugin 机制),也就是说,你需要在编译的时候选择把哪些插件编译进去

调度器的默认调度策略

Predicates预选机制()

GeneralPredicates策略

PodFitsResources 计算的就是宿主机的CPU和内存资源等是否够用.PodFitsResources检查的只是Pod的requests字段

PodFitsHost 检查的是宿主机的名字是否跟Pod的spec.nodeName一致

PodFitsHostPorts 检查的是Pod申请的宿主机端口(spec.nodePort)是不是跟已经被使用的端口有冲突

PodMatchNodeSelector检查的是,Pod的nodeSelector或者nodeAffinity指定的节点,是否与待考察节点匹配,等等

kubelet在启动Pod前,会执行一个Admit操作来进行二次确认.这里二次确认的规则,就是执行一遍 GeneralPredicates

Volumes相关的策略

NoDiskConflict 检查的条件,是多个Pod声明挂载的持久化Volume是否有冲突

maxPDVolumeCountPredicate检查的条件,则是一个节点上某种类型的持久化Volume是不是已经超过了一定数目.如果是的话,那么声明使用该类型持久化Volume的 Pod 就不能再调度到这个节点了

VolumeZonePredicate则是检查持久化Volume的Zone(高可用域)标签,是否与待考察节点的 Zone 标签相匹配

VolumeBindingPredicate的规则 它负责检查的,是该Pod对应的PV的nodeAffinity字段,是否跟某个节点的标签相匹配

在Predicates阶段Kubernetes就必须能够根据Pod的Volume属性来进行调度

宿主机相关的过滤策略

PodToleratesNodeTaints负责检查的就是我们前面经常用到的Node的“污点”机制.只有当Pod的Toleration字段与Node的Taint字段能够匹配的时候,这个Pod才能被调度到该节点上

NodeMemoryPressurePredicate检查的是当前节点的内存是不是已经不够充足,如果是的话,那么待调度Pod就不能被调度到该节点上

pod相关过滤策略

跟GeneralPredicates大多数是重合的.而比较特殊的是PodAffinityPredicate.这个规则的作用是检查待调度Pod与Node上的已有Pod之间的亲密(affinity)和反亲密(anti-affinity)关系

在为每个Node执行Predicates时调度器会按照固定的顺序来进行检查.这个顺序是按照Predicates本身的含义来确定的.比如宿主机相关的Predicates会被放在相对靠前的位置进行检查.要不然的话在一台资源已经严重不足的宿主机上,上来就开始计算PodAffinityPredicate是没有实际意义的

Priorities优选机制

Priorities阶段的工作就是为这些节点打分.这里打分的范围是 0-10 分,得分最高的节点就是最后被Pod绑定的最佳节点

Priorities里最常用到的一个打分规则

LeastRequestedPriority=score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2

这个算法实际上就是在选择空闲资源(CPU 和 Memory)最多的宿主机

BalancedResourceAllocation=score =10-variance(cpuFraction,memoryFraction,volumeFraction)*10

选择的其实是调度完成所有节点里各种资源分配最均衡的那个节点,从而避免一个节点上CPU被大量分配而 Memory大量剩余情况

Priorities里有一个叫ImageLocalityPriority的策略,如果待调度Pod需要使用的镜像很大并且已经存在于某些 Node上那么这些Node的得分就高

在实际的执行过程中,调度器里关于集群和Po 的信息都已经缓存化,所以这些算法的执行过程还是比较快的.Kubernetes调度器里其实还有一些默认不会开启的策略.可以通过为 kube-scheduler指定一个配置文件或者创建一个ConfigMap ,来配置哪些规则需要开启、哪些规则需要关闭.并且可以通过为Priorities设置权重来控制调度器的调度行为

Predicates和Priorities的区别

Predicates是为Pod过滤不符合条件的节点 返回的结果是一个满足Pod运行条件的节点列表

Priorities是为Predicates后的节点列表中的节点打分 返回的结果是为这些节点打得0-10的分数

原文地址:https://www.cnblogs.com/yxh168/p/12252239.html

时间: 2024-10-27 12:42:07

k8s的调度器架构和策略的相关文章

20.调度器,预选策略和优选策略

客户端 请求 apiserver  ------>  shceduler ------- node(kubelet或kube-proxy) 请求 apiserver 来进行pod和service创建,iptable和ipvs规则改写 调度器    先进行预选再进行优选 ,最后进行select 调度器: 预选策略: CheckNodeCondition: GeneralPredicates HostName:检查Pod对象是否定义了pod.spec.hostname, PodFitsHostPor

Linux进程核心调度器之主调度器schedule--Linux进程的管理与调度(十九)【转】

转自:http://blog.csdn.net/gatieme/article/details/51872594 日期 内核版本 架构 作者 GitHub CSDN 2016-06-30 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度 我们前面提到linux有两种方法激活调度器:核心调度器和 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要 因而内

# IT明星不是梦 # kubernetes调度器学习基础概览

scheudler是kubernetes中的核心组件,负责为用户声明的pod资源选择合适的node,同时保证集群资源的最大化利用,这里先介绍下资源调度系统设计里面的一些基础概念 基础任务资源调度 基础的任务资源调度通常包括三部分: 角色类型 功能 node node负责具体任务的执行,同时对包汇报自己拥有的资源 resource manager 汇总当前集群中所有node提供的资源,供上层的scheduler的调用获取,同时根据node汇报的任务信息来进行当前集群资源的更新 scheduler

从零开始入门 K8s | 调度器的调度流程和算法介绍

导读:Kubernetes 作为当下最流行的容器自动化运维平台,以声明式实现了灵活的容器编排,本文以 v1.16 版本为基础详细介绍了 K8s 的基本调度框架.流程,以及主要的过滤器.Score 算法实现等,并介绍了两种方式用于实现自定义调度能力. 调度流程 调度流程概览 Kubernetes 作为当下最主流的容器自动化运维平台,作为 K8s 的容器编排的核心组件 kube-scheduler 将是我今天介绍的主角,如下介绍的版本都是以 release-1.16 为基础,下图是 kube-sch

7.k8s.调度器scheduler 亲和性、污点

#k8s. 调度器scheduler 亲和性.污点 默认调度过程:预选 Predicates (过滤节点) --> 优选 Priorities(优先级排序) --> 优先级最高节点 实际使用,根据需求控制Pod调度,需要用到如下: 指定节点.nodeAffinity(节点亲和性).podAffinity(pod 亲和性). podAntiAffinity(pod 反亲和性) #指定调度节点 # Pod.spec.nodeName 强制匹配,直接指定Node 节点,跳过 Scheduler 调度

Linux内核架构读书笔记 - 2.5.4 核心调度器

什么是核心调度器? 参考前面的博文http://www.cnblogs.com/songbingyu/p/3696414.html 1 周期性调度器 作用: 管理内核中与整个系统和各个进程的调度相关的统计量 负责当前调度类的周期性调度方法 kernel/sched.c 1 /* 2 * This function gets called by the timer code, with HZ frequency. 3 * We call it with interrupts disabled. 4

k8s中的默认调度器

默认调度器中的调度算法分为预选和优选 预选策略1.基础的检查项(GeneralPredicates)PodFitsResources node剩余可分配资源(Allocatable-sum(request))是否足够pod调度PodFitsHost node的名称是否跟pod的spec.nodeName字段一致PodFitsHostPorts pod指定的spec.nodePort端口在待考察node上是否已被占用PodMatchNodeSelector pod的nodeSelector或者no

k8s调度器优先级和抢占机制

优先级(Priority)和抢占(Preemption)机制 优先级和抢占机制,解决的是Pod调度失败时该怎么办的问题 正常情况下,当一个Pod调度失败后,它就会被暂时“搁置”起来,直到Pod被更新,或者集群状态发生变化,调度器才会对这个Pod进行重新调度 特殊要求的场景: 当一个高优先级的Pod调度失败后,该Pod并不会被“搁置”,而是会“挤走”某个Node上的一些低优先级的Pod.这样就保证这个高优先级Pod的调度成功 优先级的实现 需要在Kubernetes里提交一个PriorityCla

朴素的UNIX之-调度器前传

Linux目前的进程调度算法是CFS算法,替换了之前的时间片轮转调度算法,CFS算法平滑了动态优先级的计算过程,使整个系统在任何时间都可以被任何 执行实体抢占,事实上这是分时系统的基本原则,试想,如何每一个进程/线程都像中断那样,依靠自己的优先级随时执行,那整个系统才真的成了"公平的"利他 系统.要想理解这种利他行为的本质,如果我们去研究CFS调度算法的各种统计数据,或者去研究其代码,那么其效果肯定是不好的,如果我们去研究 Windows NT内核的调度算法,无疑也会浪费大量的时间和精