44、K8S-调度机制-理论知识

发布时间 2023-04-04 18:18:50作者: 小粉优化大师

1、调度体系

1.1、流程图

1.1.1、架构层面-集群的组成

1.1.2、资源层面-k8s集群资源的管控

1.1.3、网络层面 - k8s集群资源的访问

1.1.4、认证层面-k8s集群资源的认证

1.1.5、pod周期-pod创建的完整流程

1.1.6、pod创建流程 

 

1.1.7、存储层面

 

1.1.8、创建层面 - 资源使用的数据同步

1.2、资源层面

1.2.1、资源配置项

Kubernetes技术已经对Pod做了相应的资源配额设置,目前主要包括两方面:CPU和内存

1.2.2、配额限制

Kubernetes中,对于每种资源的配额限定都需要两个参数:申请配额(Requests)和最大配额(Limits)

1.2.3、存活状态

pod层面主要是根据探针来实现的服务质量的检测:livenessProbe和readinessProbe。

1.2.4、对象分组

在kubernetes内部,尤其是pod层面,通过标签和标签选择器 或者 nodeName 等机制实现资源的分组管理。

1.2.5、服务质量

在Kubernetes内部靠实时的监控各种资源对象的状态值,对比相应的"期望状态值",然后由内部的组件做出自动的资源调整。

2、调度框架

2.1、基础知识

2.1.1、简介

前面的调度体系,全方位的梳理了一下,k8s资源调度相关的内容,但是最终的落脚点仍然要在资源上,
而这些资源本质上都是节点上的资源。所以第一步就来了,如何把资源调度到对应的节点上呢?

kube-scheduler是 kubernetes 系统的核心组件之一,主要负责整个集群资源的调度功能,根据特
定的调度算法和策略,将 Pod 调度到最优的工作节点上面去,从而更加合理、更加充分的利用集群的资源,

2.1.2、任务优先级

队列产生的原因:任务优先级的确定。
单个对象:kubectl explain pod.spec.priority
优先级组:kubectl explain pod.spec.priorityClassName

2.1.3、调度过程

 当Scheduler通过API server 的watch接口监听到新建Pod副本的信息后,它会检查所有符合该Pod
要求的Node列表,开始执行Pod调度逻辑。调度成功后将Pod绑定到目标节点上。Scheduler在整个系统中承
担了承上启下的作用,承上是负责接收创建的新Pod,为安排一个落脚的地(Node),启下是安置工作完成后,目标Node上的kubelet服务进程接管后继工作,负责Pod生命周期的后半生。

具体来说,Scheduler的作用是将待调度的Pod安装特定的调度算法和调度策略绑定到集群中的某个合 适的Node上,并将绑定信息传给API server 写入etcd中。整个调度过程中涉及三个对象,分别是:待调度的Pod列表,可以的Node列表,以及调度算法和策略。

2.1.4、调度功能

这个过程在我们看来好像比较简单,但在实际的生产环境中,需要考虑的问题就有很多了:
   1、如何保证全部的节点调度的公平性?要知道并不是说有节点资源配置都是一样的
   2、如何保证每个节点都能被分配资源?
   3、集群资源如何能够被高效利用?
   4、集群资源如何才能被最大化使用?
   5、如何保证 Pod 调度的性能和效率?
   6、用户是否可以根据自己的实际需求定制自己的调度策略?
考虑到实际环境中的各种复杂情况,kubernetes 的调度器采用插件化的形式实现,可以方便用户进行定制或者二次开发,我们可以自定义一个调度器并以插件形式和 kubernetes 进行集成。

2.2、调度模型

2.2.1、传统调度模型

预选策略(predicate)
 遍历nodelist,选择出符合要求的候选节点,过滤掉不满足条件的节点,k8s内置了多种预选规则供用户选择。
 如没有Node符合Predicates策略规则,那该Pod就会被挂起,直到有Node能够满足。
优选策略(priority) 在选择出符合要求的候选节点中,采用优选规则计算出每个节点的积分,最后选择得分最高的。
选定(
select) 如果最高得分有好几个节点,select就会从中随机选择一个节点。

2.2.2、扩展插件调度模型

虽然k8s提供了非常多的预选策略函数和优选策略函数,但是其本身的特点也限制了更多灵活场景的功能扩充,所以就出现了两种扩展方案。
多调度器
- 通过自定义调度器的方式,让用户自己来选择使用哪一种调度策略(需要用户深度参与) 扩展接口 - 通过扩展的调度接口,将相关的扩展功能整合到当前的调度策略中(每次都要编译执行)

2.2.3、新型调度策略

新型的调度框架是在传统调度逻辑的基础上,进行了整合再拆分。基本流程还是一样:队列-预选-评分绑定,将这个基本流程划分为了三个部分:
 任务队列 - 接收所有待分配的任务,任务本身会根据优先级合理调整队列的顺序。
 调度循环 - 通过扩展接口的方式整合大量的预选机制和评分机制,同时为了方便扩展,预留了备用接口
 绑定循环 - 先后通过预绑定队列(防止突发的高优先级任务出现),然后进行正常的节点任务绑定。

2.2.4、新型调度 vs 传统调度优点

1、所有的传统预选函数和优选函数,都变成了扩展插件的方式实现了动态的灵活绑定。
2、一切皆代码,所有的配置都可以通过代码的方式来进行实时调整,避免传统的再编译或用户强干预。

2.3、调度功能

2.3.1、常见的预选参数和优选参数

 

无论是传统的调度功能还是新型的调度功能,对于各种功能函数来说,本质上的逻辑变化不大,只不过在
实现细节上稍微有些不同。而且为了让调度的能力符合通用的使用,默认情况下,开启了一部分通用的策略,没有开启的策略可以通过配置参数的方式来进行扩展加载。

2.3.2、预选功能

在Kubernetes Scheduler上启用相应的预选函数才能实现相关调度机制的节点过滤需求,下面给出了这些
于Kubernetes 各版本中支持的各预选函数虽然细节实现稍有不同,但是功能基本没有怎么变,其简要功能
如下:
1)CheckNodeUnschedulable:检查节点是否被标识为Unschedulable,以及是否可将Pod调度于该类节点之上。
2)HostName:若Pod资源通过spec. nodeName明确指定了要绑定的目标节点,则节点名称与与该字段值相同的节点才会被保留。
3)PodFitsHostPorts:若Pod容器定义了ports.hostPort属性,该预选函数负责检查其值指定的端口是否已被节点上的其他容器或服务所占用,该端口已被占用的节点将被过滤掉。
4)MatchNodeSelector:若Pod资源规范上定义了spec.nodeSelector字段,则仅那些拥有匹配该标签选择器的标签的节点才会被保留。
5)NoDiskConflict:检查Pod对象请求的存储卷在此节点是否可用,不存在冲突则通过检查。
6)PodFitsResources:检查节点是否有足够资源(例如 CPU、内存和GPU等)满足Pod的运行需求;节点声明其资源可用容量,而Pod定义其资源需求(requests),于是调度器会判断节点是否有足够的可用资源
运行Pod对象,无法满足则返回失败原因(例如,CPU或内存资源不足等);调度器的评判资源消耗的标准是节点已分配资源量(各容器的requests值之和),而非其上的各Pod已用资源量,但那些在注解中标记为关
键性(critical)的Pod资源则不受该预选函数控制。
7)PodToleratesNodeTaints:检查Pod的容忍度(spec.tolerations字段)是否能够容忍该节点上的污点(taints),不过,它仅关注具有NoSchedule和NoExecute两个效用标识的污点。
8)PodToleratesNodeNoExecuteTaints:检查Pod的容忍度是否能接纳节点上定义的NoExecute类型的污点。
9)CheckNodeLabelPresence:检查节点上某些标签的存在性,要检查的标签以及其可否存在则取决于用户的定义;在集群中的部署节点以regions/zones/racks类标签的拓扑方式编制,
且基于该类标签对相应节点进行了位置标识时,预选函数可以根据位置标识将Pod调度至此类节点之上。
10)CheckServiceAffinity:根据调度的目标Pod对象所属的Service资源已关联的其他Pod对象的位置(所运行节点)来判断当前Pod可以运行的目标节点,其目的在于将同一Service对象的Pod放置在同一拓扑内(如同一个rack或zone)的节点上以提高效率。 11)MaxEBSVolumeCount:检查节点上已挂载的EBS存储卷数量是否超过了设置的最大值。 12)MaxGCEPDVolumeCount:检查节点上已挂载的GCE PD存储卷数量是否超过了设置的最大值,默认值为1613)MaxCSIVolumeCount:检查节点上已挂载的CSI存储卷数量是否超过了设置的最大值。 14)MaxAzureDiskVolumeCount:检查节点上已挂载的Azure Disk存储卷数量是否超过了设置的最大值,默认值为16。 15)MaxCinderVolumeCount:检查节点上已挂载的Cinder存储卷数量是否超过了设置的最大值。 16)CheckVolumeBinding:检查节点上已绑定和未绑定的PVC是否能满足Pod的存储卷需求,对于已绑定的PVC,此预选函数检查给定节点是否能兼容相应PV,而对于未绑定的PVC,预选函数搜索那些可满足PVC申请的可用PV,并确保它可与给定的节点兼容。 17)NoVolumeZoneConflict:在给定了存储故障域的前提下,检测节点上的存储卷是否可满足Pod定义的需求。 18)EvenPodsSpread:检查节点是否能满足Pod规范中topologySpreadConstraints字段中定义的约束以支持Pod的拓扑感知调度。 19)MatchInterPodAffinity:检查给定节点是否能满足Pod对象的亲和性或反亲和性条件,用于实现Pod亲和性调度或反亲和性调度。

2.3.3、优选功能

LeastRequestedPriority:
 优先将Pod打散至集群中的各节点之上,以试图让各节点有着近似的计算资源消耗比例,适用于集群规模
较少变动的场景;其分值由节点空闲资源与节点总容量的比值计算而来,即由CPU或内存资源的总容量减去节
点上已有Pod对象需求的容量总和,再减去当前要创建的Pod对象的需求容量得到的结果除以总容量;CPU和内
存具有相同权重,资源空闲比例越高的节点得分也就越高,其计算公式如为:(cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity))/ 2
MostRequestedPriority: 与优选函数LeastRequestedPriority的评估节点得分的方法相似,但二者不同的是,当前函数将给 予计算资源占用比例更大的节点以更高的得分,计算公式如为:(cpu((
sum(requested)) * 10 / capacity) + memory((sum(requested)) * 10 / capacity))/ 2。该函数的目标在于优先让节点 以满载的方式承载Pod资源,从而能够使用更少的节点数,因而较适用于节点规模可弹性伸缩的集群中以最大化地节约节点数量。
BalancedResourceAllocation: 以CPU和内存资源占用率的相近程度作为评估标准,二者越接近的节点权重越高。该优选函数不能单独使 用,它需要和LeastRequestedPriority组合使用来平衡优化节点资源的使用状态,选择那些在部署当前Pod资源后系统资源更为均衡的节点。
ResourceLimitsPriority: 以是否能够满足Pod资源限制为评估标准,那些能够满足Pod对于CPU或(和)内存资源限制的节点将计入1分,节点未声明可分配资源或Pod未定义资源限制时不影响节点计分。 RequestedToCapacityRatio: 该函数允许用户自定义节点各类资源(例如CPU和内存等)的权重,以便提高大型集群中稀缺资源的利用率;该函数的行为可以通过名为requestedToCapacityRatioArguments的配置选项进行控制,它由shape和resources两个参数组成。
NodeAffinityPriority: 节点亲和调度机制,它根据Pod资源规范中的spec.nodeSelector来对给定节点进行匹配度检查,成功匹配到的条目越多则节点得分越高。不过,其评估过程使用 PreferredDuringSchedulingIgnoredDuringExecution这一表示首选亲和的标签选择器。
ImageLocalityPriority: 镜像亲和调度机制,它根据给定节点上是否拥有运行当前Pod对象中的容器所依赖到的镜像文件来计算该 节点的得分值。那些不具有该Pod对象所依赖到的任何镜像文件的节点得分为0,而那些存在相关镜像文件的各节点中,拥有被Pod所依赖到的镜像文件的体积之和越大的节点得分就会越高。
TaintTolerationPriority: 基于对Pod资源对节点的污点容忍调度偏好进行其优先级评估,它将Pod对象的tolerations列表与节点的污点进行匹配度检查,成功匹配的条目越多,则节点得分越低。
SelectorSpreadPriority: 尽可能分散Pod至不同节点上的调度机制,它首先查找标签选择器能够匹配到当前Pod标签的 ReplicationController、ReplicaSet和StatefulSet等控制器对象,而后查找可由这类对象的标签选 择器匹配到的现存各Pod对象及其所在的节点,而那些运行此类Pod对象越少的节点得分越高。简单来说,如其名称所示,此优选函数尽量把同一标签选择器匹配到的Pod资源打散到不同的节点上运行。
ServiceSpreadingPriority: 类似于SelectorSpreadPriority,它首先查找标签选择器能够匹配到当前Pod标签的Service对 象,而后查找可由这类Service对象的标签选择器匹配到的现存各Pod对象及其所在的节点,而那些运行此类Pod对象越少的节点得分越高。
EvenPodsSpreadPriority: 用于将一组特定的Pod对象在指定的拓扑结构上进行均衡打散,打散条件定义在Pod对象的 spec.topologySpreadConstraints字段上,它内嵌labelSelector指定标签选择器以匹配符合条件的 Pod对象,使用topologyKey指定目标拓扑结构,使用maxSkew描述最大允许的不均衡数量,而无法满足指 定的调度条件时的评估策略则由whenUnsatisfiable字段定义,它有两个可用取值,默认值DoNotSchedule表示不予调度,而ScheduleAnyway则表示以满足最小不均衡值的标准进行调度。
EqualPriority: 设定所有节点具有相同的权重1。
InterPodAffinityPriority: 遍历Pod对象的亲和性条目,并将那些能够匹配到给定节点的条目的权重相加,结果值越大的节点得分越高。
NodePreferAvoidPodsPriority: 此优选级函数权限默认为10000,它根据节点是否设置了注解信息scheduler.alpha.kubernetes.io
/preferAvoidPods来计算其优选级。计算方式是,给定的节点无此 注解信息时,其得分为10乘以权重10000,存在此注解信息时,对于那些由ReplicationController或ReplicaSet控制器管控的Pod对象的得分为0,其他Pod对象会被忽略(得最高分)。

2.4、调度梳理

调度策略     解析
节点调度     为即将执行的任务,选择合理的节点
Pod调度      为即将执行的任务,分配合理的逻辑关联搭配
污点调度     在任务调度的时候,设定一些避免措施
拓扑调度     在任务已确定调度的前提下,合理的分配任务,实现资源的高效利用

2.5、调度思路

2.5.1、亲和与反亲和

满足条件后,就分配 或者 远离 指定的节点。

2.5.2、硬亲和与软亲和

不会遵循绝对的条件阈值,而是根据实际情况,做出倾向性策略
硬亲和会考量预选和优选策略,而软亲和仅考虑优选策略