客户端通过 API Server 的 REST API 或者 kubectl 工具创建 Pod 资源

API Server 收到用户请求后,存储相关数据到 etcd 数据库中

调度器监听 API Server 查看到还未被调度(bind)的 Pod 列表,循环遍历地为每个 Pod 尝试分配节点,这个分配过程提到的两个阶段:

预选阶段(Predicates),过滤节点,调度器用一组规则过滤掉不符合要求的 Node 节点,比如 Pod 设置了资源的 request,那么可用资源比 Pod 需要的资源少的主机显然就会被过滤掉
优选阶段(Priorities),为节点的优先级打分,将上一阶段过滤出来的 Node 列表进行打分,调度器会考虑一些整体的优化策略,比如把 Deployment 控制的多个 Pod 副本尽量分布到不同的主机上,使用最低负载的主机等等策略

经过上面的阶段过滤后选择打分最高的 Node 节点和 Pod 进行 binding 操作,然后将结果存储到 etcd 中, 最后被选择出来的 Node 节点对应的 kubelet 去执行创建 Pod 的相关操作(当然也是 watch APIServer 发现的)

  • 首先是预选过程,过滤掉不满足条件的节点,这个过程称为 Predicates(过滤)
  • 然后是优选过程,对通过的节点按照优先级排序,称之为Priorities(打分)
  • 最后从中选择优先级最高的节点,如果中间任何一步骤有错误,就直接返回错误

两个阶段

Predicates 预选阶段
首先遍历全部节点,过滤掉不满足条件的节点,属于强制性规则,这一阶段输出的所有满足要求的节点将被记录并作为第二阶段的输入,如果所有的节点都不满足条件,那么 Pod 将会一直处于 Pending 状态,直到有节点满足条件,在这期间调度器会不断的重试

在部署应用时如果发现有 Pod 一直处于 Pending 状态,那么就是没有满足调度条件的节点,这个时候可以去检查下节点资源是否可用

Priorities 优选阶段
再次对节点进行筛选,如果有多个节点都满足条件的话,那么系统会按照节点的优先级(priorites)大小对节点进行排序,最后选择优先级最高的节点来部署 Pod 应用

predicate 预选策略

PodFitsResources
节点上剩余的资源(如 CPU 和内存)是否满足 Pod 请求的资源

PodFitsHost
如果 Pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配

PodFitsHostPorts
如果 Pod 中定义了 hostPort 属性,检查这个指定端口是否已经被节点上其他服务占用了

PodMatchNodeSelector
检查 Node 的标签是否能匹配 Pod 的 nodeSelector 的标签值

NoDiskConflict
检查 Pod 请求的存储卷在 Node 上是否可用,若不存在冲突则通过检查

NoVolumeZoneConflict
检测 Pod 请求的 Volumes 在节点上是否可用,因为某些存储卷存在区域调度约束

CheckNodeDiskPressure
检查节点磁盘空间是否符合要求

CheckNodeMemoryPressure
检查节点内存是否够用

CheckNodeCondition
Node 可以上报其自身的状态,如磁盘、网络不可用,表明 kubelet 未准备好运行 Pod,如果节点被设置成这种状态,那么 Pod 不会被调度到这个节点上

PodToleratesNodeTaints
检查 Pod 属性上的 tolerations 能否容忍节点的 taints 污点

CheckVolumeBinding
检查节点上已经绑定的和未绑定的 PVC 能否满足 Pod 的存储卷需求

priority 优选策略

由一系列键值对组成的,键是该优先级的名称,值是它的权重值

LeastRequestedPriority
通过计算 CPU 和内存的使用率来决定权重,使用率越低权重越高,运行 Pod 的可能性就越大
BalancedResourceAllocation
优选资源利用率更为均衡的节点
ImageLocalityPriority
Node 上已经拥有 Pod 需要的容器镜像的 Node 会有较高的优先级
镜像越大权重值越高
SelectorSpreadPriority
为了更好的高可用,对同属于一个 Deployment 或者 RC 下面的多个 Pod 副本,尽量调度到多个不同的节点上,当一个 Pod 被调度的时候,会先去查找该 Pod 对应的 controller,然后查看该 controller 下面的已存在的 Pod,运行 Pod 越少的节点权重越高
InterPodAffinityPriority
遍历 Pod 的亲和性条目,并将那些能够匹配到给定节点的条目的权重相加,结果值越大的节点得分越高
MostRequestedPriority
空闲资源比例越低的 Node 得分越高,这个调度策略将会把你的所有的工作负载(Pod)调度到尽量少的节点上
RequestedToCapacityRatioPriority
为 Node 上每个资源占用比例设定得分值,给资源打分函数在打分时使用
NodePreferAvoidPodsPriority
这个策略将根据 Node 的注解信息中是否含有 scheduler.alpha.kubernetes.io/preferAvoidPods 来计算其优先级,使用这个策略可以将两个不同 Pod 运行在不同的 Node 上
NodeAffinityPriority
基于 Pod 属性中 PreferredDuringSchedulingIgnoredDuringExecution 来进行 Node 亲和性调度
TaintTolerationPriority
基于 Pod 中对每个 Node 上污点容忍程度进行优先级评估,这个策略能够调整待选 Node 的排名
ServiceSpreadingPriority
这个调度策略的主要目的是确保将归属于同一个 Service 的 Pod 调度到不同的 Node 上,如果 Node 上没有归属于同一个 Service 的 Pod,这个策略更倾向于将 Pod 调度到这类 Node 上。最终的目的:即使在一个 Node 宕机之后 Service 也具有很强容灾能力。
CalculateAntiAffinityPriorityMap
这个策略主要是用来实现 Pod 反亲和的
EqualPriorityMap
将所有的 Node 设置成相同的权重为 1