3. K8s 调度基础:调度器工作原理、节点选择、Pod 调度流程

在 GitOps 流水线中,每一次代码合并都可能触发新的 Pod 部署。理解 Kubernetes 调度器(kube-scheduler)的工作原理,是优化同步窗口、控制 Pod 分布、避免资源争抢的前提。本章从调度器架构、节点选择机制、Pod 调度全流程三个维度展开,为后续“调度优化与同步窗口集成”打下基础。

3.1 调度器工作原理

Kubernetes 调度器是一个独立的控制平面组件,负责将未调度的 Pod(spec.nodeName 为空)绑定到最合适的 Node 上。其核心是一个“过滤 → 打分 → 绑定”的三阶段循环。

关键概念:调度器不直接启动 Pod,而是通过 API Server 更新 Pod 的 nodeName 字段,由目标节点的 kubelet 负责实际创建。

3.1.1 调度器架构组件

组件 职责 可扩展性
调度队列 管理待调度 Pod,支持优先级排序、重试、回退 可自定义队列排序策略
过滤阶段 从所有 Node 中选出满足 Pod 硬性约束的节点 通过 Predicate 扩展点注入自定义过滤逻辑
打分阶段 对过滤后的 Node 进行优先级评分,选出最优节点 通过 Priority 扩展点注入自定义打分算法
绑定阶段 将 Pod 与选定 Node 的绑定关系写入 API Server 支持异步绑定、多调度器协调

3.1.2 调度器工作流程(内联 SVG)

调度器三阶段工作流程 阶段 1:过滤 Predicate 扩展点 节点选择器、亲和性 污点容忍、资源充足 阶段 2:打分 Priority 扩展点 资源均衡、亲和性加分 自定义权重策略 阶段 3:绑定 写入 API Server 更新 Pod nodeName 触发 kubelet 创建 输入与输出 输入:未调度 Pod(nodeName=“”)+ 当前集群 Node 列表 输出:Pod 与最优 Node 的绑定关系(写入 etcd) 调度队列管理 activeQ(活跃队列)→ backoffQ(回退队列)→ unschedulableQ(不可调度队列) 优先级排序、周期重试、失败 Pod 回退指数

3.2 节点选择机制

节点选择是调度器在过滤阶段的核心工作。Kubernetes 提供了多种机制让用户控制 Pod 可以调度到哪些节点上,这些机制在 GitOps 流水线中常用于隔离环境、绑定硬件、实现合规性。

3.2.1 节点选择机制对比

机制 匹配方式 典型场景 调度阶段
nodeSelector 精确匹配 Label 键值对 简单环境隔离(如 env=prod) 过滤
节点亲和性 支持 In/NotIn/Exists/Gt/Lt 等操作符 复杂拓扑约束、硬件类型选择 过滤 + 打分
Pod 亲和性/反亲和性 基于已有 Pod 的 Label 分布 服务就近部署、故障域隔离 过滤 + 打分
污点与容忍 Node 标记污点,Pod 声明容忍 专用节点(GPU)、节点维护 过滤
GitOps 实践提示:在 Helm Chart 或 Kustomize 中,将环境标签(如 env: staging)作为 nodeSelector 的默认值,可以防止流水线误将测试 Pod 调度到生产节点。

3.2.2 节点选择决策树(内联 SVG)

节点选择决策树(过滤阶段) Pod 调度请求 污点容忍检查 Node 污点 vs Pod 容忍 节点选择器/亲和性 Label 匹配规则 资源可用性检查 CPU/内存/GPU/端口 全部通过 → 进入打分阶段 任意检查失败 → 节点被过滤 失败原因记录到 Pod 事件(describe pod 可见),Pod 进入 unschedulableQ 等待重试 调度器按指数退避(5s → 10s → 20s …)重新尝试

3.3 Pod 调度流程

一个 Pod 从创建到运行在节点上,经历了完整的调度生命周期。理解这个流程,有助于在 GitOps 流水线中定位调度延迟、资源不足、调度失败等问题。

3.3.1 完整调度流程步骤

  1. Pod 创建:用户或控制器(Deployment/Job)通过 API Server 创建 Pod 对象,spec.nodeName 为空。
  2. 调度器监听:kube-scheduler 通过 Watch 机制发现未调度的 Pod,将其加入调度队列(activeQ)。
  3. 过滤阶段:调度器遍历所有 Node,执行 Predicate 函数(节点选择器、污点容忍、资源充足、端口冲突等),生成候选节点列表。
  4. 打分阶段:对候选节点执行 Priority 函数(资源均衡、亲和性加分、自定义策略),每个节点获得 0-100 分。
  5. 选定节点:选择最高分节点;若多个节点同分,随机选择一个。
  6. 绑定:调度器通过 API Server 创建 Binding 对象,将 Pod 的 nodeName 设置为选定节点。
  7. kubelet 响应:目标节点的 kubelet 监听到 Pod 更新,调用容器运行时(containerd/CRI-O)启动容器。
  8. 状态上报:kubelet 将 Pod 状态更新为 Running,调度流程结束。
常见调度失败原因:
  • 资源不足(CPU/Memory 请求超过节点剩余容量)
  • 节点选择器/亲和性无匹配节点
  • 节点存在未容忍的污点(如 node.kubernetes.io/unschedulable)
  • 端口冲突(Pod 使用 hostPort 且端口已被占用)
  • 存储卷挂载冲突(PVC 被绑定到特定节点拓扑)

3.3.2 调度流程时序图(内联 SVG)

Pod 调度流程时序 用户/控制器 API Server 调度器 kubelet 容器运行时 创建 Pod 存储 Pod 过滤+打分 绑定 更新 nodeName 拉取镜像 启动容器 状态 Running

3.4 调度器扩展点与 GitOps 集成

Kubernetes 调度器支持通过 Scheduling Framework 注入自定义扩展点。在 GitOps 流水线中,可以利用这些扩展点实现调度策略的声明式管理。

3.4.1 主要扩展点

扩展点 阶段 典型用途
PreFilter 过滤前 预处理 Pod 信息,提前排除无效节点
Filter 过滤 自定义节点过滤逻辑(如 GPU 型号匹配)
PreScore 打分前 计算全局评分上下文
Score 打分 自定义权重评分(如网络延迟、成本)
Reserve 绑定前 预留资源,防止并发冲突
Permit 绑定前 批准或延迟绑定(实现调度门控)
GitOps 集成建议:将自定义调度器扩展(如 scheduler-config.yaml)作为 GitOps 仓库中的版本化资源,通过 Argo CD 或 Flux 同步到集群。当需要调整调度策略(如增加成本权重、修改节点过滤规则)时,只需修改 Git 仓库中的配置,流水线自动完成更新。

3.5 本章小结

  • 调度器核心是 过滤 → 打分 → 绑定 三阶段循环,所有扩展点都围绕这三个阶段展开。
  • 节点选择机制包括 nodeSelector、节点亲和性、Pod 亲和性/反亲和性、污点与容忍,在 GitOps 中应声明式定义。
  • Pod 调度流程涉及 API Server、调度器、kubelet、容器运行时 四个角色,理解时序有助于排查调度延迟。
  • 调度器扩展点(Scheduling Framework)允许自定义调度逻辑,适合通过 GitOps 进行版本化管理。