一、调度简介
kube-scheduler是Kubernetes中的关键模块,扮演管家的角色遵从一套机制为Pod提供调度服务,例如基于资源的公平调度、调度Pod到指定节点、或者通信频繁的Pod调度到同一节点等。容器调度本身是一件比较复杂的事,因为要确保以下几个目标:
-
公平性:在调度Pod时需要公平的进行决策,每个节点都有被分配资源的机会,调度器需要对不同节点的使用作出平衡决策。
-
资源高效利用:最大化群集所有资源的利用率,使有限的CPU、内存等资源服务尽可能更多的Pod。
-
效率问题:能快速的完成对大批量Pod的调度工作,在集群规模扩增的情况下,依然保证调度过程的性能。
-
灵活性:在实际运作中,用户往往希望Pod的调度策略是可控的,从而处理大量复杂的实际问题。因此平台要允许多个调度器并行工作,同时支持自定义调度器。
二、调度流程
kube-scheduler的根本工作任务是根据各种调度算法将Pod绑定(bind)到最合适的工作节点,整个调度流程分为两个阶段:预选策略(Predicates)和优选策略(Priorities)。
-
预选(Predicates):输入是所有节点,输出是满足预选条件的节点。kube-scheduler根据预选策略过滤掉不满足策略的Nodes。例如,如果某节点的资源不足或者不满足预选策略的条件如“Node的label必须与Pod的Selector一致”时则无法通过预选。
-
优选(Priorities):输入是预选阶段筛选出的节点,优选会根据优先策略为通过预选的Nodes进行打分排名,选择得分最高的Node。例如,资源越富裕、负载越小的Node可能具有越高的排名。
通俗点说,调度的过程就是在回答两个问题:1. 候选有哪些?2. 其中最适合的是哪个?
值得一提的是,如果在预选阶段没有节点满足条件,Pod会一直处在Pending状态直到出现满足的节点,在此期间调度器会不断的进行重试。
调度器每次只调度一个pod资源对象,为每一个pod资源对象寻找合适节点的过程是一个调度周期
Kube-scheduler调度器在为pod资源对象选择合适的节点时,有以下两种最优解:
全局最优解:指每个调度周期都会遍历k8s集群中所有节点,以便找出最优节点(集群规模较小,几百台机器时使用)
局部最优解:指每个调度周期都只会遍历部分的k8s节点,找出局部最优解(集群规模较大时使用,比如5000台机器时使用)
2.1 预选策略算法
CheckNodeConditionPred: 检查节点是否处于就绪状态
GeneralPred : 检查节点上的pod资源对象数量上限,以及CPU,内存,GPU等资源是否符合要求
CheckNodeMemoryPressure: 检查pod资源是否可以调度到可使用内存过低的节点上
PodToleratesNodeTaints:若当前节点被标记为Taints,检查pod资源对象是否能容忍Node Taints
MatchInterPodAffinity: 检查节点是否能满足pod的亲和性或反亲和性
CheckNodeLabelPresence: 检查指定的标签再上节点是否存在
除此之外还有基于存储卷的判断等策略
2.2 优选策略算法(Priorities)
优选过程会根据优选策略对每个候选节点进行打分,最终把Pod调度到分值最高的节点。kube-scheduler用一组优先级函数处理每个通过预选的节点,每个函数返回0-10 的分数,各个函数有不同权重,最终得分是所有优先级函数的加权和
-
LeastRequestedPriority(默认权重1):尽量将Pod调度到计算资源占用比较小的Node上
-
BalancedResourceAllocation(默认权重1):CPU和内存使用率越接近的节点权重越高。该策略均衡了节点CPU和内存的配比,尽量选择在部署Pod后各项资源更均衡的机器。该函数不能单独使用,必须和LeastRequestedPriority同时使用,因为如果请求的资源(CPU或者内存)大于节点的capacity(节点现有容量),那么该节点永远不会被调度到。
-
SelectorSpreadPriority(默认权重1):把属于同一个Service或者ReplicationController的Pod,尽量分散在不同的节点上,如果指定了区域,则尽量把Pod分散在该区域的不同节点。通常来说节点上已运行的Pod越少,节点分数越高。
-
NodeAffinityPriority(默认权重1):尽量调度到标签匹配Pod属性要求的节点
该函数提供两种选择器:requiredDuringSchedulingIgnoredDuringExecution(硬亲和)和preferredDuringSchedulingIgnoredDuringExecution(软亲和)。前者是强要求,指定将Pod调度到节点上必须满足的所有规则;后者是弱要求,即尽可能调度到满足特定限制的节点,但允许不满足。
-
TaintTolerationPriority(默认权重1):Pod与Node的排斥性判断。通过Pod的tolerationList与节点Taint进行匹配,配对失败的项越少得分越高,类似于Predicates策略中的PodToleratesNodeTaints。
-
ImageLocalityPriority(默认权重1):尽量调度到Pod所需镜像的节点。检查Node是否存在Pod所需镜像:如果不存在,返回0分;如果存在,则镜像越大得分越高。
调度算法执行完成后,调度器就需要将 Pod 对象的 nodeName 字段的值,修改为k8s选择的node的名字。
2.3 调度时的资源需求
CPU:
requests: k8s调度pod时,会判断当前节点正在运行的Pod的CPU request的总和,再加上当前调度Pod的 CPU request ,计算 其是否超过节点的CPU的可分配资源
imits :配置cgroup以 限制资源上限
内存:
requests:判断节点的剩余内存是否满足pod的内存请求量,以确定是否可以将pod调度到该节点
limits :配置cgroup以限制资源上限
kc get deployment saber-saber-qturq -n medusa -o yaml
kc get node g1-med-online1-120 -o yaml
allocatable:节点可分配资源
capacity:节点一共有这些资源 去除不能分配的资源就是allocatable
limits:应用最多只能用这么多资源
requests :调度器调度时参考的值,一个应用至少需要这么多资源才能起来 调度的时候只看这个部分,调度后,节点会把这部分资源从节点剩余资源中扣除掉
2. 4 QoS
QoS(Quality of Service),大部分译为 “服务质量等级”
,又译作 “服务质量保证”
,是作用在 Pod 上的一个配置,当k8s创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:
Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值。
Burstable:Pod 里至少有一个容