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

取样调度里面的取样规模这里简单介绍一下,默认的取样比率公式 = Max (5, 50 - 集群的 node 数 / 125),取样规模 = Max (100, 集群 Node 数*取样比率)。

这里举个例子:节点规模为 3000 个节点,那么**取样比例 = Max (5, 50 - 3000/125) = 26%,那么取样规模 *= Max (100, 3000 0.26) = 780,在调度流水线里面,Filter 只要匹配到 780 个候选节点,就可以停止 Filter 流程,走到 Score 阶段。

Score 阶段依据 Policy 配置的算分插件,进行排序,分数最高的节点作为 SelectHost。接着将这个 Pod 分配到这个 Node 上,这个过程叫做 Reserver 阶段可以称为账本预占。预占的过程修改 Pod 在 PodCache 的状态为 Assumed 的状态(处于内存态)。

调度过程涉及到 Pod 状态机的生命周期,这里简单介绍下 Pod 的几个主要状态: Initial(虚拟状态)->Assumed(Reserver)->Added->Deleted(虚拟状态); 当通过 Informer watch 到 Pod 数据已经确定分配到这个节点的时候,才会把 Pod 的状态变成 Added。选中完节点在 Bind 的时候,有可能会 Bind 失败,在 Bind 失败的时候会做回退,就是把预占用的账本做 Assumed 的数据退回 Initial,也就是把 Assumed 状态擦除,从 Node 里面把 Pod 账本清除。

如果 Bind 失败,会把 Pod 重新丢回到 unschedulableQ 队列里面。在调度队列中,什么情况下 Pod 会到 backoffQ 中呢?这是一个很细节的点。如果在这么一个调度周期里面,Cache 发生了变化,会把 Pod 放到 backoffQ 里面。在 backoffQ 里面等待的时间会比在 unschedulableQ 里面时间更短,backoffQ 里有一个降级策略,是 2 的指数次幂降级。假设重试第一次为 1s,那第二次就是 2s,第三次就是 4s,第四次就是 8s,最大到 10s。

调度算法实现 Predicates (过滤器)

Filter 根据功能用途可以把它们分为四类:

存储匹配相关

Pode 和 Node 匹配相关

Pod 和 Pod 匹配相关

Pod 打散相关

存储相关

存储相关的几个过滤器的功能:

NoVolumeZoneConflict,pvc 关联的 pv 的 label 上设置 zone\az 限制待匹配的节点要跟 pv;

MaxCSIVolumeCountPred,是用来校验 pvc 上指定的 Provision 在 CSI plugin 上的单机最大 pv 数限制;

CheckVolumeBindingPred,在 pvc 和 pv 的 binding 过程中对其进行逻辑校验,里头的逻辑写的比较复杂,主要都是如何复用 pv;

NoDiskConfict,SCSI 存储不会被重复的 volume。

Pod 和 Node 匹配相关

CheckNodeCondition:校验节点是否准备好被调度,校验node.condition的condition type :Ready为true和NetworkUnavailable为false以及Node.Spec.Unschedulable为false;

CheckNodeUnschedulable:在 node 节点上有一个 NodeUnschedulable 的标记,我们可以通过 kube-controller 对这个节点直接标记为不可调度,那这个节点就不会被调度了。在 1.16 的版本里,这个 Unschedulable 已经变成了一个 Taints。也就是说需要校验一下 Pod 上打上的 Tolerates 是不是可以容忍这个 Taints;

PodToleratesNodeTaints:校验 Node 的 Taints 是否被 Pod Tolerates 包含;

PodFitsHostPorts:校验 Pod 上的 Container 声明的 Ports 是否正在被 Node 上已经分配的 Pod 使用;

MatchNodeSelector: 校验 Pod.Spec.Affinity.NodeAffinity 和 Pod.Spec.NodeSelector 是否与 Node 的 Labels 匹配。

Pod 和 Pod 匹配相关

MatchinterPodAffinity:主要是 PodAffinity 和 PodAntiAffinity 的校验逻辑,这里面最大的复杂度是在于 Affinity 里面的 PodAffinityTerm 描述支持的 TopologyKey(可以表示在 node/zone/az 等拓扑结构上),这个其实是一个性能杀手。

Pod 打散相关

EvenPodsSpread

CheckServiceAffinity

EvenPodsSpread

这是一个新的功能特性,首先来看一下 EvenPodsSpread 中 Spec 描述:
-- 描述符合条件的一组 Pod 在指定 TopologyKey 上的打散要求。

下面我们来看一下怎么描述一组 Pod,如下图所示:

spec: topologySpreadConstraints: - maxSkew: 1 whenUnsatisfiable: DoNotSchedule topologyKey: k8s.io/hostname selector: matchLabels: app: foo matchExpressions: - key: app operator: In values: [\'foo\', \'foo2\']

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwzwxj.html