摘要:与已运行相关的过滤规则负责检查待调度与上已有之间的亲和性关系。并且每个打分函数都可以配置对应的权重值,下面介绍调度器策略配置时,也会涉及权重值的配置。默认权重值是,如果觉得某个打分函数特别重要,便可以加大该权重值。
一、概述
Kubernetes 是 Google 开源的容器集群管理系统(谷歌内部:Borg),而今天要介绍的 kube-scheduler 是 k8s 系统的核心组件之一,其主要职责就是通过自身的调度算法,为新创建的 Pod 寻找一个最合适的 Node。
主要包含如下几个步骤:
通过一组叫做谓词 predicates 的过滤算法,先挑出满足条件的 Node;
通过一组叫做优先级 priorities 的打分算法,来给上一步符合条件的每个 Node 进行打分排名;
最终选择得分最高的节点,当然如果得分一样就随机一个节点,填回 Pod 的 spec.nodeName 字段。
官方流程图如下:
For given pod: +---------------------------------------------+ | Schedulable nodes: | | | | +--------+ +--------+ +--------+ | | | node 1 | | node 2 | | node 3 | | | +--------+ +--------+ +--------+ | | | +-------------------+-------------------------+ | | v +-------------------+-------------------------+ Pred. filters: node 3 doesn"t have enough resource +-------------------+-------------------------+ | | v +-------------------+-------------------------+ | remaining nodes: | | +--------+ +--------+ | | | node 1 | | node 2 | | | +--------+ +--------+ | | | +-------------------+-------------------------+ | | v +-------------------+-------------------------+ Priority function: node 1: p=2 node 2: p=5 +-------------------+-------------------------+ | | v select max{node priority} = node 2
scheduler 的工作看似很简单,但其实不然。考虑的问题非常多,比如要保证每个节点被公平调度,提高资源利用率,提高 pod 调度效率,提升调度器扩展能力等等。
可涉及的内容非常多,接下来会围绕两个核心步骤对 k8s 的 默认调度策略 深入了解。
参考 Kubernetes 版本: v1.12二、Predicates
Predicates 在调度过程中的作用就是先进行过滤,过滤掉所有不符合条件的节点后,剩下的所有节点就都是可以运行带调度 Pod。
Predicates 的可以分为如下四类:
GeneralPredicates:负责最基础的调度策略,比如 PodFitsResources 计算宿主机资源是否够用。
与 Volume 相关的过滤规则:负责与容器持久化 Volume 相关的调度策略。
与宿主机相关的过滤规则:负责考察待调度 Pod 是否满足 Node 本身的一些条件。
与已运行 Pod 相关的过滤规则:负责检查待调度 Pod 与 Node 上已有 Pod 之间的亲和性关系。
具体的 Predicates 默认策略,可以参考: 默认调度策略
当开始调度一个 Pod 的时候,调度器会同时开启多个协程并发的进行 Node Predicates 过滤,最后返回一个可以运行 Pod 的节点列表。每个协程都是按照固定的顺序进行计算过滤的。
接下来,我们看下四大类具体运行的调度策略内容。
1. GeneralPredicates看字面意思就知道 GeneralPredicates 负责的是最基础的调度策略,其包含的具体策略如下:
PodFitsResources: 计算宿主机的 CPU、内存、扩展资源(如 GPU)等是否够用。
PodFitsHost: 检查宿主机的名字是否跟 Pod 的 spec.nodeName 匹配。
PodFitsHostPorts: 检查 Pod 申请的宿主机端口有没有冲突。
PodMatchNodeSelector: 检查节点是否能匹配 Pod 的 nodeSelector 和 nodeAffinity。
因为 GeneralPredicates 是最基础的调度策略,所以该接口也会被别的组件直接调用,比如 kubelet、daemonSet controller。kubelet 在启动 pod 之前,还会再执行一遍 GeneralPredicates,用于二次确认。
2. 与 Volume 相关的过滤规则不废话就直接列举具体的策略了:
NoDiskConflict:检查该节点上所有的 Pods 是否与待调度的 Pod 的 Volume 有冲突,比如 AWS、GCE 的 Volume 是不允许被两个 Pod 同时使用的。
VolumeZonePredicate:检查 Pod Volume 的 zone 标签是否与节点的 zone 标签匹配。如果 Node 没有 zone 标签则认定为匹配。
MaxPDVolumeCountPredicate:检查节点上某种类型的 Volume 是否已经超过指定数目。
CSIMaxVolumeLimitPredicate:检查 csi volume 相关的限制
VolumeBindingPredicate:检查 Pod 对应的 Local PV 的 nodeAffinity 字段,是否跟某个节点的标签相匹配。如果该 Pod PVC 还没有绑定 PV 的话,则调度器还要负责检查所有待绑定的 PV,且该 PV 的 nodeAffinity 是否与节点标签匹配。
3. 与宿主机相关的过滤规则这些规则主要考察待调度的 Pod 是否满足 Node 本身的一些条件。
具体的策略如下:
NodeConditionPredicate:检查 Node 是否还未准备好或者处于NodeOutOfDisk、NodeNetworkUnavailable 状态,又或者 Node spec.Unschedulable 设置为 true,那该节点都将无法被调度。
PodToleratesNodeTaints:检查 Node 的 taint(污点)机制。只有当 Pod 的 Toleration 与 Node 的 Taint 匹配时,Pod 才能调度到该节点上。
NodeMemoryPressurePredicate:检查当前节点的内存是否已经不够使用。
NodeDiskPressurePredicate:检查当前节点的磁盘是否已经不够使用。
NodePIDPressurePredicate:检查当前节点的 PID 是否已经不够使用。
4. 与已运行 Pod 相关的过滤规则该规则主要就是 PodAffinityPredicate,用于检查待调度 Pod 与 Node 上已有的 Pod 之间的亲和性和反亲和性关系。
具体的亲和性相关的调度,后面会多带带拿一篇文章进行介绍。
完成了前一个阶段的节点 “过滤” 之后,便需要通过 Priorities 为这些节点打分,选择得分最高的节点,作为调度对象。
打分函数很多,总得分可以参考:
总分 = (权重1 * 打分函数1) + (权重2 * 打分函数2) + … + (权重n * 打分函数n)。
每一次打分的范围是 0 — 10 分。10 表示非常合适,0 表示非常不合适。
并且每个打分函数都可以配置对应的权重值,下面介绍 调度器策略配置 时,也会涉及权重值的配置。默认权重值是 1,如果觉得某个打分函数特别重要,便可以加大该权重值。
具体的 Priorities 默认策略可以参考: defaultPriorities 。
Priorities 最常用到的一个打分规则是 LeastRequestedPriority, 该算法用于选出空闲资源(cpu & memory)最多的宿主机。
还有一个常见的是 BalancedResourceAllocation,该规则主要目的是资源平衡。在所有节点里选择各种资源分配最均衡的节点,避免出现某些节点 CPU 被大量分配,但是 Memory 大量剩余的情况。
此外,还有 InterPodAffinityPriority、NodeAffinityPriority、TaintTolerationPriority,与亲和性与污点调度有关,后面会有多带带的文章进行介绍。这里表示节点满足的规则越多,那得分就越高。
在 K8S v1.12 版本还引入了一个调度策略,即 ImageLocalityPriority。该策略主要目的是优先选择那些已经存有 Pod 所需 image 的节点,可以避免实际运行 Pod 时,再去下载 image。
注意: pod 运行时是否会下载 image,还跟 Pod ImagePullPolicy 配置有关。
可以看到 k8s scheduler 完成一次调度所需的信息非常之多。所以在实际的调度过程中,大量的信息都事先已经缓存,提高了 Pod 的调度效率。
四、调度策略配置Kubernetes 调度器有默认的调度策略,具体可以参考 default 。当然用户也可以修改调度策略,可以通过命令行参数 policy-config-file 指定一个 JSON 文件来描述哪些 predicates 和 priorities 在启动 k8s 时被使用, 通过这个参数调度就能使用管理者定义的策略了。
示例如下:
{ "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "PodFitsHostPorts"}, {"name" : "PodFitsResources"}, {"name" : "NoDiskConflict"}, {"name" : "NoVolumeZoneConflict"}, {"name" : "MatchNodeSelector"}, {"name" : "HostName"} ], "priorities" : [ {"name" : "LeastRequestedPriority", "weight" : 1}, {"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} ], "hardPodAffinitySymmetricWeight" : 10, "alwaysCheckAllPredicates" : false }五、自定义调度器
前面提到了调度器的扩展能力,除了使用 k8s 自带的调度器,你也可以编写自己的调度器。通过修改 Pod 的 spec.schedulername 参数来指定调度器的名字。
参考资料The Kubernetes Scheduler
Scheduler Algorithm in Kubernetes
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/32908.html
摘要:换句话说,亲和性选择节点仅在调度时起作用。先创建集群反亲和性打散各个副本再部署服务,需要打散并且与服务共存,配置如下注意需要进行大量处理,所以会明显减慢大型集群的调度时间,不建议在大于几百个节点的集群中使用该功能。 一、概述 前一篇文章 Kubernetes 调度器浅析,大致讲述了调度器的工作原理及相关调度策略。这一章会继续深入调度器,介绍下亲和性调度。 Kubernetes 支持限制...
摘要:本文将主要分析原生的网络策略。笔者认为这个问题主要是因为使用者不了解网络策略的省缺行为。可选字段,字符串,策略规则类型,表示该网络策略中包含哪些类型的策略,可选为或。互相间为或的关系,满足其中一条则放行。标准,除了指定的放行外其他都禁止。 k8s中的网络策略主要分为原生 NetworkPolicy 和第三方网络插件提供的网络策略。本文将主要分析原生Networkpolicy的网络策略。...
摘要:在这种情况下,以防干扰其他集群租户,调度器可能会考虑将作为驱逐的候选对象。其结果是负载均衡和调度之间交互作用。 每当谈及Kubernetes,我们经常听到诸如资源管理、调度和负载均衡等术语。虽然Kubernetes提供了许多功能,但更关键的还是要了解这些概念,只有这样才能更好地理解如何放置、管理并恢复工作负载。在这篇文章中,我提供了每个功能的概述,并解释了它们是如何在Kubernete...
阅读 3094·2021-09-10 10:51
阅读 3302·2021-08-31 09:38
阅读 1593·2019-08-30 15:54
阅读 3106·2019-08-29 17:22
阅读 3182·2019-08-26 13:53
阅读 1924·2019-08-26 11:59
阅读 3226·2019-08-26 11:37
阅读 3280·2019-08-26 10:47