Kubernetes 调度器
在 Kubernetes 中,调度 是指将 PodPod 是 Kubernetes 的原子对象。Pod 表示您的集群上一组正在运行的容器。 放置到合适的 NodeKubernetes 中的工作机器称作节点。 上,然后对应 Node 上的 Kubelet一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。 才能够运行这些 pod。
调度概览
调度器通过 kubernetes 的 watch 机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。调度器会依据下文的调度原则来做出调度选择。
如果你想要理解 Pod 为什么会被调度到特定的 Node 上,或者你想要尝试实现一个自定义的调度器,这篇文章将帮助你了解调度。
kube-scheduler
kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群 控制面容器编排层,它暴露 API 和接口来定义、部署容器和管理容器的生命周期。 的一部分。如果你真的希望或者有这方面的需求,kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。
对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会选择一个最优的 Node 去运行这个 Pod。然而,Pod 内的每一个容器对资源都有不同的需求,而且 Pod 本身也有不同的资源需求。因此,Pod 在被调度到 Node 上之前,根据这些特定的资源调度需求,需要对集群中的 Node 进行一次过滤。
在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 _可调度节点_。如果没有任何一个 Node 能满足 Pod 的资源请求,那么这个 Pod 将一直停留在未调度状态直到调度器能够找到合适的 Node。
调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分,然后选出其中得分最高的 Node 来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做 _绑定_。
在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。
kube-scheduler 调度流程
kube-scheduler 给一个 pod 做调度选择包含两个步骤:
过滤
打分
过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下,这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。
在打分阶段,调度器会为 Pod 从所有可调度节点中选取一个最合适的 Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。
最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。
默认策略
kube-scheduler 有一系列的默认调度策略。
过滤策略
PodFitsHostPorts
:如果 Pod 中定义了 hostPort 属性,那么需要先检查这个指定端口是否 已经被 Node 上其他服务占用了。PodFitsHost
:若 pod 对象拥有 hostname 属性,则检查 Node 名称字符串与此属性是否匹配。PodFitsResources
:检查 Node 上是否有足够的资源(如,cpu 和内存)来满足 pod 的资源请求。PodMatchNodeSelector
:检查 Node 的 标签用来为对象设置可标识的属性标记;这些标记对用户而言是有意义且重要的。 是否能匹配 Pod 属性上 Node 的 标签用来为对象设置可标识的属性标记;这些标记对用户而言是有意义且重要的。 值。NoVolumeZoneConflict
:检测 pod 请求的 Volumes包含可被 Pod 中容器访问的数据的目录。 在 Node 上是否可用,因为某些存储卷存在区域调度约束。NoDiskConflict
:检查 Pod 对象请求的存储卷在 Node 上是否可用,若不存在冲突则通过检查。MaxCSIVolumeCount
:检查 Node 上已经挂载的 CSI容器存储接口 (CSI)定义了存储系统暴露给容器的标准接口。 存储卷数量是否超过了指定的最大值。CheckNodeMemoryPressure
:如果 Node 上报了内存资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。CheckNodePIDPressure
:如果 Node 上报了 PID 资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。CheckNodeDiskPressure
:如果 Node 上报了磁盘资源压力过大(文件系统满了或者将近满了), 而且配置没有异常,那么 Pod 将不会被调度到这个 Node 上。CheckNodeCondition
:Node 可以上报其自身的状态,如磁盘、网络不可用,表明 kubelet 未准备好运行 pod。 如果 Node 被设置成这种状态,那么 pod 将不会被调度到这个 Node 上。PodToleratesNodeTaints
:检查 pod 属性上的 tolerations一个核心对象,由三个必需的属性组成:key、value 和 effect。容忍度允许将 Pod 调度到具有对应污点的节点或节点组上。 能否容忍 Node 的 taints一个核心对象,由三个必需的属性组成:键,值和效果。污点会阻止在节点或节点组上调度 Pod。 。CheckVolumeBinding
:检查 Node 上已经绑定的和未绑定的 PVCs声明在持久卷中定义的存储资源,以便可以将其挂载为容器中的卷。 能否满足 Pod 对象的存储卷需求。
打分策略
SelectorSpreadPriority
:尽量将归属于同一个 Service将运行在一组 {{< glossary_tooltip text=“Pods” term_id=“pod” >}} 上的应用程序公开为网络服务的抽象方法。 、StatefulSetStatefulSet 用来管理 Deployment 和伸缩一组 Pod,并且能为这些 Pod 提供*序号和唯一性保证*。 或 ReplicaSetReplicaSet 是下一代副本控制器。 的 Pod 资源分散到不同的 Node 上。InterPodAffinityPriority
:遍历 Pod 对象的亲和性条目,并将那些能够匹配到给定 Node 的条目的权重相加,结果值越大的 Node 得分越高。LeastRequestedPriority
:空闲资源比例越高的 Node 得分越高。换句话说,Node 上的 Pod 越多,并且资源被占用的越多,那么这个 Node 的得分就会越少。MostRequestedPriority
:空闲资源比例越低的 Node 得分越高。这个调度策略将会把你所有的工作负载(Pod)调度到尽量少的 Node 上。RequestedToCapacityRatioPriority
:为 Node 上每个资源占用比例设定得分值,给资源打分函数在打分时使用。BalancedResourceAllocation
:优选那些使得资源利用率更为均衡的节点。NodePreferAvoidPodsPriority
:这个策略将根据 Node 的注解信息中是否含有scheduler.alpha.kubernetes.io/preferAvoidPods
来 计算其优先级。使用这个策略可以将两个不同 Pod 运行在不同的 Node 上。NodeAffinityPriority
:基于 Pod 属性中 PreferredDuringSchedulingIgnoredDuringExecution 来进行 Node 亲和性调度。你可以通过这篇文章 Pods 到 Nodes 的分派 来了解到更详细的内容。TaintTolerationPriority
:基于 Pod 中对每个 Node 上污点容忍程度进行优先级评估,这个策略能够调整待选 Node 的排名。ImageLocalityPriority
:Node 上已经拥有 Pod 需要的 容器镜像镜像是保存的容器实例,它打包了应用运行所需的一组软件。 的 Node 会有较高的优先级。ServiceSpreadingPriority
:这个调度策略的主要目的是确保将归属于同一个 Service 的 Pod 调度到不同的 Node 上。如果 Node 上 没有归属于同一个 Service 的 Pod,这个策略更倾向于将 Pod 调度到这类 Node 上。最终的目的:即使在一个 Node 宕机之后 Service 也具有很强容灾能力。CalculateAntiAffinityPriorityMap
:这个策略主要是用来实现pod反亲和。EqualPriorityMap
:将所有的 Node 设置成相同的权重为 1。