深入解析 Kubernetes 调度系统
Posted JFrog杰蛙DevOps
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入解析 Kubernetes 调度系统相关的知识,希望对你有一定的参考价值。
点击蓝字
优良的调度是分布式系统的核心。Scheduler 调度器做为 Kubernetes 三大核心组件之一, 承载着整个集群资源的调度功能,其根据特定调度算法和策略,将 Pod 调度到最优工作节点上,从而更合理与充分的利用集群计算资源,使资源更好的服务于业务服务的需求。
随着业务服务不断 Docker 化与微服务化,Kubernetes 集群规模不断的扩大,而 Kubernetes 调度器作为集群的中枢系统,在如何提高集群的底层计算资源利用率、保证集群中服务的稳定运行中也就变得尤为重要。
背景介绍
Kubernetes 的架构设计基本上是参照了 Google Borg。Google 的 Borg 系统群集管理器负责管理几十万个以上的 jobs,来自几千个不同的应用,跨多个集群,每个集群有上万个机器。它通过管理控制、高效的任务包装、超售、和进程级别性能隔离实现了高利用率。它支持高可用性应用程序与运行时功能,最大限度地减少故障恢复时间,减少相关故障概率的调度策略。
基于资源分配的任务调度是 Kubernetes 的核心组件。Kubernetes 的调度策略源自 Borg, 但是为了更好的适应新一代的容器应用,以及各种规模的部署,Kubernetes 的调度策略相应做的更加灵活,也更加容易理解和使用。
Kubernetes 基本架构如下:
其中, Controller Manager 主要用于管理计算节点(Node Controller)以及Pod副本(Replication Controller)等,Scheduler 根据特定的算法和策略调度 Pod 到具体的计算节点, Kubelet 通过 apiserver 或者监控本地的配置文件(eg. Kubeadm 创建的 Kuernetes 集群),通过 docker daemon 创建 Pod 的 container。
调度流程
默认配置情况下,Kubernetes 调度器能够满足绝大多数要求,例如保证 Pod 只会被分配到资源足够的节点上运行,把同一个集合的 Pod 分散在不同的计算节点上,平衡不同节点的资源使用率等。
但在绝大多数情况下,用户比 Kubernetes 更了解自己的应用。有时候,我们希望 Pod 调度可控,便于更好的满足业务对资源的需求。例如希望某个 Pod 只运行在有特定硬件的节点上,或者想要让频繁互相通信的服务能就近部署,或者希望用独立的节点给部分用户提供服务等。
Scheduler 是 Kubernetes 的调度器,其作用是根据特定的调度算法和策略将 Pod 调度到指定的计算节点(Node)上,其做为单独的程序运行,启动之后会一直监听 API Server,获取 PodSpec.NodeName 为空的 Pod,对每个 Pod 都会创建一个绑定(binding)。
普通用户可以把 Scheduler可理解为一个黑盒,黑盒的输入为待调度的 Pod 和全部计算节点的信息,经过黑盒内部的调度算法和策略处理,输出为最优的节点,而后将 Pod 调度该节点上 。
这个过程看起来似乎比较简单,但实际生产环境的调度过程中,有很多问题需要考虑:
首先,如何保证全部计算节点调度的公平性?如何保证每个节点都能被分配资源?
其次,计算资源如何能够被高效利用?集群所有计算资源如何才能被最大化的使用?
再次,如何保证 Pod 调度的性能和效率?如何能够快速的对大批量的 Pod 完成调度到较优的计算节点之上?
最后,用户最了解自己的业务,用户是否可以根据实际需求定制自己的调度逻辑和策略?
调度策略
Kubernetes 的调度器以插件化形式实现的,方便用户定制和二次开发。用户可以自定义调度器并以插件形式与 Kubernetes 集成,或集成其他调度器,便于调度不同类型的任务。
Kubernetes 调度器的源码位于 kubernetes/plugin/ 中,大体的代码目录结构如下所示:
Scheduler 创建和运行的过程,对应的代码在 plugin/pkg/scheduler/scheduler.go。
上面初步介绍了 Kubernetes 调度器。具体的说,调度器是 Kubernetes 容器集群管理系统中加载并运行的调度程序,负责收集、统计分析容器集群管理系统中所有 Node 的资源使用情况,然后以此为依据将新建的 Pod 发送到优先级最高的可用 Node 上去建立。
调度分为几个部分:首先是预选过程,过滤掉不满足条件的节点,这个过程称为 Predicates;然后是优选过程,对通过的节点按照优先级排序,称之为 Priorities;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。
进一步说:
Predicates 阶段回答“能不能”的问题:首先遍历全部节点,过滤掉不满足条件的节点,这一阶段输出的所有满足要求的 Node 将被记录并作为第二阶段的输入。
Priorities 阶段是回答“哪个更适合的问题”:即再次对节点进行筛选,筛选出最适合运行 Pod 的节点。
如果在预选(Predicates)过程中,如果所有的节点都不满足条件,Pod 会一直处在 Pending 状态,直到有节点满足条件,这期间调度器会不断的重试。经过节点过滤后,如多个节点满足条件,会按照节点优先级(priorities)大小对节点排序,最后选择优先级最高的节点部署 Pod。
调度过程的简单图示如下:
具体的调度过程,一般如下:
首先,客户端通过 API Server 的 REST API/kubectl/helm 创建 pod/service/deployment/job 等,支持类型主要为 JSON/YAML/helm tgz。
接下来,API Server 收到用户请求,存储到相关数据到 etcd。
调度器通过 API Server 查看未调度(bind)的 Pod 列表,循环遍历地为每个 Pod 分配节点,尝试为 Pod 分配节点。调度过程分为2个阶段:
第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如 Pod 指定了所需要的资源量,那么可用资源比 Pod 需要的资源量少的主机会被过滤掉。
第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个 Replication Controller 的副本分布到不同的主机上,使用最低负载的主机等。
选择主机:选择打分最高的节点,进行 binding 操作,结果存储到 etcd 中。
所选节点对于的 kubelet 根据调度结果执行 Pod 创建操作。
Kubernetes 调度器使用 Predicates 和 Priorites 来决定一个 Pod 应该运行在哪一个节点上。Predicates 是强制性规则,用来形容主机匹配 Pod 所需要的资源,如果没有任何主机满足该 Predicates,则该 Pod 会被挂起,直到有节点能够满足调度条件。
预选(Predicates)与优选(Priorites)的策略罗列如下:
接下来,分别介绍调度器 Scheduler 的预选与优选两个阶段。
预选(Predicates)
下面分别对 Predicates 的策略进行介绍:
NoDiskConflict:pod 所需的卷是否和节点已存在的卷冲突。如果节点已经挂载了某个卷,其它同样使用这个卷的 pod 不能再调度到这个主机上。GCE、Amazon EBS 与 Ceph RBD 的规则如下:
NoVolumeZoneConflict:检查给定的 zone 限制前提下,检查如果在此主机上部署 Pod 是否存在卷冲突。假定一些 volumes 可能有 zone 调度约束, VolumeZonePredicate 根据 volumes 自身需求来评估 pod 是否满足条件。必要条件就是任何 volumes 的 zone-labels 必须与节点上的 zone-labels 完全匹配。节点上可以有多个 zone-labels 的约束(比如一个假设的复制卷可能会允许进行区域范围内的访问)。目前,这个只对 PersistentVolumeClaims 支持,而且只在 PersistentVolume 的范围内查找标签。处理在 Pod 的属性中定义的 volumes(即不使用 PersistentVolume)有可能会变得更加困难,因为要在调度的过程中确定 volume 的 zone,这很有可能会需要调用云提供商。
PodFitsResources:检查节点是否有足够资源(例如 CPU、内存与GPU等)满足一个 Pod 的运行需求。调度器首先会确认节点是否有足够的资源运行 Pod,如果资源不能满足 Pod 需求,会返回失败原因(例如,CPU/内存不足等)。这里需要注意的是:根据实际已经分配的资源量做调度,而不是使用已实际使用的资源量做调度。
请参见我之前写的文章:《Kubernetes 之服务质量保证(QoS)》(http://dockone.io/article/2592)。
PodFitsHostPorts:检查 Pod 容器所需的 HostPort 是否已被节点上其它容器或服务占用。如果所需的 HostPort 不满足需求,那么 Pod 不能调度到这个主机上。
注:1.0版本被称之为 PodFitsPorts,1.0之后版本变更为 PodFitsHostPorts,为了向前兼容 PodFitsPorts 名称仍然保留。
HostName:检查节点是否满足 PodSpec 的 NodeName 字段中指定节点主机名,不满足节点的全部会被过滤掉。
MatchNodeSelector:检查节点标签(label)是否匹配 Pod 的 nodeSelector 属性要求。关于 nodeSelector 请参见我之前写的文章:《Kubernetes 之 Pod 调度 》(http://dockone.io/article/2635)。
MaxEBSVolumeCount:确保已挂载的EBS存储卷不超过设置的最大值(默认值为39。Amazon 推荐最大卷数量为40,其中一个卷为 root 卷,具体可以参考http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volumelimits.html#linux-specific-volume-limits)。调度器会检查直接使用以及间接使用这种类型存储的 PVC。计算不同卷的总和,如果卷数目会超过设置的最大值,那么新 Pod 不能调度到这个节点上。 最大卷的数量可通过环境变量 KUBEMAXPDVOLS 设置。
MaxGCEPDVolumeCount:确保已挂载的 GCE 存储卷不超过预设的最大值(GCE 默认值最大存储卷值为16,具体可参见https://cloud.google.com/compute/docs/disks/persistent-disks#limitsforpredefinedmachinetypes)。与 MaxEBSVolumeCount 类似,最大卷的数量同样可通过环境变量 KUBEMAXPD_VOLS 设置。
MaxAzureDiskVolumeCount : 确保已挂载的 Azure 存储卷不超过设置的最大值。默认值是16。规则同 MaxEBSVolumeCount。
CheckNodeMemoryPressure : 判断节点是否已经进入到内存压力状态,如果是则只允许调度内存为0标记的 Pod。检查 Pod 能否调度到内存有压力的节点上。如有节点存在内存压力, Guaranteed类型的Pod(例如,requests 与 limit 均指定且值相等) 不能调度到节点上。
QoS 相关请参见我之前写的文章:《Kubernetes 之服务质量保证(QoS)》(http://dockone.io/article/2592)。
CheckNodeDiskPressure : 判断节点是否已经进入到磁盘压力状态,如果是,则不调度新的 Pod。
PodToleratesNodeTaints : 根据 taints 和 toleration 的关系判断 Pod 是否可以调度到节点上 Pod 是否满足节点容忍的一些条件。
MatchInterPodAffinity : 节点亲和性筛选。
GeneralPredicates:包含一些基本的筛选规则,主要考虑 Kubernetes 资源是否充足,比如 CPU 和 内存 是否足够,端口是否冲突、selector 是否匹配等:
1. PodFitsResources:检查主机上的资源是否满足 Pod 的需求。资源的计算是根据主机上运行 Pod 请求的资源作为参考的,而不是以实际运行的资源数量。
2. PodFitsHost:如果 Pod 指定了 spec.NodeName,看节点的名字是否何它匹配,只有匹配的节点才能运行 Pod。
3. PodFitsHostPorts:检查 Pod 申请的主机端口是否已经被其他 Pod 占用,如果是,则不能调度。
4. PodSelectorMatches:检查主机的标签是否满足 Pod 的 selector。包括 NodeAffinity 和 nodeSelector 中定义的标签。
关于 predicates 更多详细的细节,
请参考plugin/pkg/scheduler/algorithm/predicates/predicates.go:(https://github.com/kubernetes/kubernetes/blob/28e0c3bef21f0df658e40ab5cfb148c85b7daea5/plugin/pkg/scheduler/algorithm/predicates/predicates.go)。
关于节点亲和性(Affinity)、Pod 亲和性(Affinity)与反亲和性(anti-affinity)以及污点(Taints)与容忍(tolerations)等调度的使用。
请参见我之前写的文章:《Kubernetes 之 Pod 调度》(http://dockone.io/article/2635)。
优选(Priorities)
经过预选策略(Predicates)对节点过滤后,获取节点列表,再对符合需求的节点列表进行打分,最终选择 Pod 调度到一个分值最高的节点。Kubernetes 用一组优先级函数处理每一个通过预选的节点(kubernetes/plugin/pkg/scheduler/algorithm/priorities 中实现)。每一个优先级函数会返回一个0-10的分数,分数越高表示节点越优, 同时每一个函数也会对应一个表示权重的值。最终主机的得分用以下公式计算得出:
finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + … + (weightn * priorityFuncn)
目前支持优选的优先级函数包括以下几种:
LeastRequestedPriority:节点的优先级就由节点空闲资源与节点总容量的比值,即由(总容量-节点上 Pod 的容量总和-新 Pod 的容量)/总容量)来决定。CPU 和内存具有相同权重,资源空闲比越高的节点得分越高。需要注意的是,这个优先级函数起到了按照资源消耗来跨节点分配 Pod 的作用。详细的计算规则如下:
cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2
注:10 表示非常合适,0 表示完全不合适。
LeastRequestedPriority 举例说明:例如 CPU 的可用资源为100,运行容器申请的资源为15,则 CPU 分值为8.5分,内存可用资源为100,运行容器申请资源为20,则内存分支为8分。则此评价规则在此节点的分数为(8.5 +8) / 2 = 8.25分。
BalancedResourceAllocation:CPU 和内存使用率越接近的节点权重越高,该策略不能单独使用,必须和 LeastRequestedPriority 组合使用,尽量选择在部署 Pod 后各项资源更均衡的机器。如果请求的资源(CPU 或者内存)大于节点的 capacity,那么该节点永远不会被调度到。
BalancedResourceAllocation 举例说明:该调度策略是出于平衡度的考虑,避免出现 CPU,内存消耗不均匀的事情。例如某节点的 CPU 剩余资源还比较充裕,假如为100,申请10,则 cpuFraction 为0.1,而内存剩余资源不多,假如为20,申请10,则 memoryFraction 为0.5,这样由于 CPU 和内存使用不均衡,此节点的得分为10-abs ( 0.1 - 0.5 ) * 10 = 6 分。假如 CPU 和内存资源比较均衡,例如两者都为0.5,那么代入公式,则得分为10分。
InterPodAffinityPriority:通过迭代 weightedPodAffinityTerm 的元素计算和,并且如果对该节点满足相应的 PodAffinityTerm,则将 “weight” 加到和中,具有最高和的节点是最优选的。
SelectorSpreadPriority:为了更好的容灾,对同属于一个 service、replication controller 或者 replica 的多个 Pod 副本,尽量调度到多个不同的节点上。如果指定了区域,调度器则会尽量把 Pod 分散在不同区域的不同节点上。当一个 Pod 的被调度时,会先查找 Pod 对于的 service 或者 replication controller,然后查找 service 或 replication controller 中已存在的 Pod,运行 Pod 越少的节点的得分越高。
SelectorSpreadPriority 举例说明:这里主要针对多实例的情况下使用。例如,某一个服务,可能存在5个实例,例如当前节点已经分配了2个实例了,则本节点的得分为10*((5-2)/ 5)=6分,而没有分配实例的节点,则得分为10 * ((5-0) / 5)=10分。没有分配实例的节点得分越高。
注:1.0版本被称之为 ServiceSpreadingPriority,1.0之后版本变更为 SelectorSpreadPriority,为了向前兼容 ServiceSpreadingPriority 名称仍然保留。
NodeAffinityPriority:Kubernetes 调度中的亲和性机制。Node Selectors(调度时将pod限定在指定节点上),支持多种操作符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限于对节点 labels 的精确匹配。另外,Kubernetes 支持两种类型的选择器,一种是“hard(requiredDuringSchedulingIgnoredDuringExecution)”选择器,它保证所选的主机必须满足所有 Pod 对主机的规则要求。这种选择器更像是之前的 nodeselector,在 nodeselector 的基础上增加了更合适的表现语法。另一种是“soft(preferresDuringSchedulingIgnoredDuringExecution)”选择器,它作为对调度器的提示,调度器会尽量但不保证满足 NodeSelector 的所有要求。
NodePreferAvoidPodsPriority(权重1W):如果节点的 Anotation 没有设置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = "...",则节点对该 policy 的得分就是10分,加上权重10000,那么该 node 对该 policy 的得分至少10W分。如果 Node 的 Anotation 设置了,scheduler.alpha.kubernetes.io/preferAvoidPods = "..." ,如果该 pod 对应的 Controller 是 ReplicationController 或 ReplicaSet,则该 node 对该 policy 的得分就是0分。
TaintTolerationPriority : 使用 Pod 中 tolerationList 与节点 Taint 进行匹配,配对成功的项越多,则得分越低。
另外在优选的调度规则中,有几个未被默认使用的规则:
ImageLocalityPriority:根据 Node 上是否存在一个 pod 的容器运行所需镜像大小对优先级打分,分值为0-10。遍历全部 Node,如果某个 Node 上 pod 容器所需的镜像一个都不存在,分值为0;如果 Node 上存在 Pod 容器部分所需镜像,则根据这些镜像的大小来决定分值,镜像越大,分值就越高;如果 Node 上存在 pod 所需全部镜像,分值为10。
注:10 表示非常合适,0 表示完全不合适
EqualPriority : EqualPriority 是一个优先级函数,它给予所有节点相等权重。
MostRequestedPriority : 在 ClusterAutoscalerProvider 中,替换 LeastRequestedPriority,给使用多资源的节点,更高的优先级。计算公式为:(cpu(10 sum(requested) / capacity) + memory(10 sum(requested) / capacity)) / 2
要想获得所有节点最终的权重分值,就要先计算每个优先级函数对应该节点的分值,然后计算总和。因此不管过程如何,如果有 N 个节点,M 个优先级函数,一定会计算 M*N 个中间值,构成一个二维表格:
最后,会把表格中按照节点把优先级函数的权重列表相加,得到最终节点的分值。上面代码就是这个过程,中间过程可以并发计算(下文图中的workQueue),以加快速度。
自定义调度
使用 kube-schduler 的默认调度就能满足大部分需求。在默认情况下,Kubernetes 调度器可以满足绝大多数需求,例如调度 Pod 到资源充足的节点上运行,或调度 Pod 分散到不同节点使集群节点资源均衡等。前面已经提到,kubernetes 的调度器以插件化的形式实现的, 方便用户对调度的定制与二次开发。下面介绍几种方式:
方式一:定制预选(Predicates) 和优选(Priority)策略
kube-scheduler 在启动的时候可以通过 --policy-config-file 参数可以指定调度策略文件,用户可以根据需要组装 Predicates 和 Priority 函数。选择不同的过滤函数和优先级函数、控制优先级函数的权重、调整过滤函数的顺序都会影响调度过程。
考官方给出的 Policy 文件实例:
方式二:自定义 Priority 和 Predicate
上面的方式一是对已有的调度模块进行组合,Kubernetes 还允许用户编写自己的 Priority 和 Predicate 函数。
过滤函数的接口:
自定义 Predicates 函数步骤如下:
在 plugin/pkg/scheduler/algorithm/predicates/predicates.go 文件中编写对象实现上面接口。
编写完过滤函数之后进行注册,让 kube-scheduler 启动的时候知道它的存在,注册部分可以在 plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go 完成,可以参考其他过滤函数(例如PodFitsHostPorts)的注册代码:kubernetes/plugin/pkg/scheduler/algorithmprovider/defaults/defaults.gofactory.RegisterFitPredicate("PodFitsPorts", predicates.PodFitsHostPorts)。
在 --policy-config-file 把自定义过滤函数写进去,kube-scheduler 运行时可以执行自定义调度逻辑了。
自定义优先级函数,实现过程和过滤函数类似。
方式三:编写自己的调度器
除了上面2种方式外,Kubernetes 也允许用户编写自己的调度器组件,并在创建资源的时候引用它。多个调度器可以同时运行和工作,只要名字不冲突。
使用某个调度器就是在 Pod 的 spec.schedulername 字段中填写上调度器的名字。Kubernetes 提供的调度器名字是 default,如果自定义的调度器名字是 my-scheduler,那么只有当 spec.schedulername 字段是 my-scheduler 才会被调度。
调度器最核心的逻辑并不复杂。Scheduler 首先监听 apiserver ,获取没有被调度的 Pod 和全部节点列表,而后根据一定的算法和策略从节点中选择一个作为调度结果,最后向 apiserver 中写入 binding 。比如下面就是用 bash 编写的简单调度器:
它通过 kubectl 命令从 apiserver 获取未调度的 Pod(spec.schedulerName 是my-scheduler,并且 spec.nodeName 为空),同样地,用 kubectl 从 apiserver 获取 nodes 的信息,然后随机选择一个 node 作为调度结果,并写入到 apiserver 中。
当然要想编写一个生产级别的调度器,要完善的东西还很多,比如:
调度过程中需要保证 Pod 是最新的,这个例子中每次调度 pod 的时候,它在 apiserver 中的内容可能已经发生了变化
调度过程需要考虑资源等因素(节点的资源利用率,存储和网络的信息等)
尽量提高调度的性能(使用并发来提高调度的性能)
可通过 kubectl describe pod pod_name 查看一个 Pod 采用的调度器,例如:
Pod 优先级(Priority)
和抢占(Preemption)
Pod 优先级(Priority)
Pod 优先级(Priority)和抢占(Preemption)是 Kubernetes 1.8版本引入的功能,在1.8版本默认是禁用的,当前处于 Alpha 阶段,不建议在生产环境使用。
与前面所讲的调度优选策略中的优先级(Priorities)不同,前文所讲的优先级指的是节点优先级,而 pod priority 指的是 Pod 的优先级,高优先级的 Pod 会优先被调度,或者在资源不足低情况牺牲低优先级的 Pod,以便于重要的 Pod 能够得到资源部署。
为了定义 Pod 优先级,需要先定义 PriorityClass 对象,该对象没有 Namespace 限制,官网示例:
然后通过在 Pod 的 spec. priorityClassName 中指定已定义的 PriorityClass 名称即可:
抢占(Preemption)
当节点没有足够的资源供调度器调度 Pod、导致 Pod 处于 pending 时,抢占(preemption)逻辑会被触发。Preemption 会尝试从一个节点删除低优先级的 Pod,从而释放资源使高优先级的 Pod 得到节点资源进行部署。
Pod 优先级(Priority)和抢占(preemption)具体介绍可参见 https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/。回过头来,再重新看一下 Pod 的调度过程,也许会清晰很多。如下图示例:
注:使用 workQueue 来并行运行检查,并发数最大是16。
对应源码示例:orkqueue.Parallelize(16, len(nodes), checkNode)。
总结
本次分享主要介绍了 Pod 的预选与优选调度策略、Kubernetes 调度的定制与开发,以及 Kubernetes1.8的 Pod 优先级和抢占等新特性。
没有什么事情是完美的,调度器也一样,用户可结合实际业务服务特性和需求,利用或定制 Kubernetes 调度策略,更好满足业务服务的需求。
Q&A
Q:普通用户有自定义 Pod 优先级的权限吗?
A:可以,Pod 优先级定义与创建普通 Pod 类似,并没有特别权限控制。定义 Pod 优先级,需要先定义 kind 为 PriorityClass 类型的资源对象,然后通过在 Pod 的 spec. priorityClassName 中指定已定义的 PriorityClass 名称即可。
Q:Kubernetes scheduler extender 能介绍一下么?
A:extender 可理解为 Kubernetes 调度策略和算法的扩展,属于自定义调度器的一种方式,与 Kubernetes 默认调度器的过程类似,主要是针对一些不算受集群本身控制的资源(比如网络),需要通过外部调用来进行调度的情况。
Q:用户使用了 NodeSelector 指定了 Pod 调度的 node 节点后,如果 node 不可用,那么 scheduler 会采用别的策略吗?
A:nodeSelector 是目前最为简单的一种 pod 运行时调度限制,目前在 Kubernetes 1.7.x及以下版本可用。Pod.spec.nodeSelector 通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,而后调度 Pod 到目标节点,该匹配规则属于强制约束,如果 node 不可用,Pod 会一直处于 pending 状态。nodeAffinity 具备 nodeSelector 的全部功能,所以未来 Kubernetes 会将 nodeSelector 废除。
今日推荐阅读
关于JFrog
世界领先DevOps平台
公司成立于2008年,在美国、以色列、法国、西班牙,以及中国北京市拥有超过200名员工。JFrog 拥有4000多个付费客户,其中知名公司包括如腾讯、谷歌、思科、Netflix、亚马逊、苹果等。关注 JFrog,感受原汁原叶的硅谷技术!我们不仅仅提供最优秀的产品,也提供最优秀的持续交付平台的解决方案,详情请洽info@jfrogchina.com
点击“阅读原文”,进入 JFrog 官网
以上是关于深入解析 Kubernetes 调度系统的主要内容,如果未能解决你的问题,请参考以下文章