调度程序决定 pod 在集群中的部署位置,这听起来像是一项简单的工作,但它相当复杂!当使用 kubectl 提交部署时,API 服务器会收到请求,并将资源存储在 etcd 中。

一、谁创建了 Pod?

一个常见的误解是创建 pod 是调度程序的工作。相反,控制器管理器创建它们(以及关联的 ReplicaSet)。

Pod 资源存储在 Etcd 中

此时,pod 在 etcd 中存储为“Pending”,未分配给任何节点。它们也被添加到调度程序的队列中,准备好被分配。

Pod 被添加到调度程序队列中

二、调度绑定

调度程序通过两个阶段 1 个 1 个地处理 Pod:

  1. 调度阶段(我应该选择什么节点?)
  2. 绑定阶段(将此 pod 所属于的节点信息写入数据库)

Pod 一次分配一个

Scheduler阶段分为两部分。调度程序:

  1. 过滤相关节点(Predicates 预选策略),强制性规则,遍历所有的Node,按照具体的预选策略筛选出符合要求的Node列表,如没有Node符合Predicates策略规则,那该Pod就会被挂起,直到有Node能够满足;
  2. 对剩余节点进行排名(Priorites优选策略),优选策略,在第一步筛选的基础上,按照优选策略为待选Node打分排序,获取最优者;

参考页面:
Kubernetes Scheduler分析
k8s官网调度策略文档

三、GPU调度示例

让我们看一个例子,比如我们有一个带和不带 GPU 的节点的集群。此外,一些节点已经满负荷运行。

您想要部署需要一些 GPU 的 Pod,将 pod 提交到集群,它被添加到调度程序队列中。调度器丢弃所有没有 GPU 的节点(过滤阶段)。

丢弃所有非 GPU 节点并给其余节点打分

接下来,调度程序对剩余的节点进行评分。充分利用的节点得分较低,最后会选择空节点。

过滤器的分类示例:

  • NodeUnschedulable防止 pod 调度标记为不可调度的节点
  • VolumeBinding检查节点是否可以绑定请求的卷

建议参考:kube-scheduler predicates 与 priorities 调度算法源码分析

默认过滤阶段有 13 个 断言(Predicates)— 这部分要根据实际k8s版本而定,不同版本内容也在更新

Kubernetes 调度器中的默认Predicates

以下是一些评分示例:

  • ImageLocality首选已在本地下载容器映像的节点。
  • NodeResourcesBalancedAllocation更喜欢未充分利用的节点。

有 13 个函数决定如何对节点进行评分和排名 — 每个 priority 函数为 node 打分,分数为 0-10 ,0 表示优先级最低的节点,10表示优先级最高的节点

在 Kubernetes 中对节点进行评分的默认函数

四、控制调度程序的决策

控制调度程序的决策方式主要有以下这些:

  • nodeSelector
  • Node affinity
  • Pod affinity/anti-affinity
  • Taints and tolerations
  • Topology constraints
  • Scheduler profiles

nodeSelector 是最直接的机制,将标签分配给节点并将该标签添加到 pod,Pod 只能部署在具有该标签的节点上。

使用 nodeSelector 将 pod 分配给节点

Node affinity 节点亲和性通过更灵活的接口扩展了 nodeSelector,您仍然可以告诉调度器 Pod 应该部署在哪里,但是您也可以有软约束和硬约束。

将 pod 分配给具有节点亲和力的节点

Pod affinity/anti-affinity 使用 Pod 亲和性/反亲和性,您可以要求调度程序将一个 pod 放置在特定 pod 旁边(或排斥某pod)。

使用 Pod 亲和性和反亲和性调度 Pod

Taints and tolerations 有了污点和容忍度,pod 被污染,节点排斥(或容忍)pod ,这类似于节点亲和性,但有一个显着的区别:对于节点亲和性,Pod 被吸引到节点上。污点恰恰相反——它们允许节点排斥 pod。

使用污点和容忍度调度 pod

此外,容忍度可以通过三种效果排斥 pod:逐出、“不调度”和“强列不调度(双重否定)”。个人说明:这是我使用过的最困难的 API 之一。我总是(并且一直)把它弄错,因为(对我来说)很难用双重否定来推理。

Topology constraints 您可以使用拓扑分布约束来控制 Pod 在集群中的分布方式 。当您要确保所有 Pod 不落在同一个节点上时,这很方便。

Pod 拓扑约束

Scheduler profiles 最后,您可以使用调度程序策略来自定义调度程序如何使用过滤器和谓词将节点分配给 Pod。这个相对较新的功能 (>1.25) 允许您关闭或向调度程序添加新逻辑。

Kubernetes 中的调度程序策略

您可以在此处了解有关调度程序的更多信息:

本篇内容基于 Daniele Polencic的文章 翻译再加工。