3. Pod 调度基础:Pod 调度生命周期、调度队列、调度周期与绑定周期

Pod 调度是 Kubernetes 调度器的核心职责。理解 Pod 从创建到被调度到合适节点的完整生命周期,是掌握调度优化与故障排查的前提。本章将深入剖析调度器内部的三个关键阶段:调度队列、调度周期与绑定周期,并梳理 Pod 调度的整体生命周期。

3.1 Pod 调度生命周期全景

一个 Pod 从提交到运行,其调度相关生命周期可划分为以下阶段:

阶段 描述 关键组件
1. 创建与入队 用户通过 API Server 创建 Pod,调度器通过 Informer 机制监听未调度的 Pod,将其加入调度队列。 API Server、Informer、Scheduling Queue
2. 出队与调度周期 调度器从队列中取出一个 Pod,执行预选(Predicates)和优选(Priorities)算法,选出最优节点。 Scheduler Framework、Filter、Score
3. 绑定周期 调度器将选定的节点信息写入 Pod 的 NodeName 字段,并异步执行绑定操作。 Binder、API Server
4. 节点确认与运行 Kubelet 监听到 Pod 被调度到本节点,拉取镜像并启动容器。 Kubelet、Container Runtime
关键认知: 调度器只负责“决策”,不负责“执行”。调度周期决定 Pod 应该去哪个节点,绑定周期负责将这个决策持久化到 etcd,而真正的容器启动由 Kubelet 完成。

3.2 调度队列:Pod 的等待区

调度队列是调度器的入口,负责管理所有等待调度的 Pod。Kubernetes 默认使用 PriorityQueue,它内部维护了三个子队列:

  • activeQ:存放所有准备好被调度的 Pod,按优先级排序。
  • backoffQ:存放调度失败的 Pod,经过退避时间后重新进入 activeQ。
  • unschedulableQ:存放因资源不足、节点污点等原因无法调度的 Pod,等待集群状态变化后重新尝试。
调度队列核心机制:
  • 优先级排序:Pod 优先级(PriorityClass)越高,出队越早。
  • 抢占式调度:高优先级 Pod 可以抢占低优先级 Pod 的资源。
  • 退避机制:调度失败的 Pod 会进入 backoffQ,退避时间指数增长(如 1s、2s、4s...),避免频繁重试。
  • 事件驱动:当集群资源变化(如新节点加入、Pod 删除)时,unschedulableQ 中的 Pod 会被重新评估。
调度队列内部结构(PriorityQueue) activeQ 就绪 Pod 按优先级排序 立即出队 backoffQ 调度失败 Pod 退避等待 指数退避 unschedulableQ 不可调度 Pod 等待资源变化 事件驱动重试 出队 退避到期 集群事件触发 调度周期 预选 → 优选 → 选定节点

3.3 调度周期:预选与优选

调度周期是调度器的核心决策阶段,分为两个步骤:预选(Filter) 和 优选(Score)。

3.3.1 预选阶段(Filtering)

预选阶段的目标是快速过滤掉不满足条件的节点,生成一个可行节点列表。常见的预选策略包括:

预选策略 作用 典型场景
NodeResourcesFit 检查节点剩余资源(CPU、内存)是否满足 Pod 请求 Pod 请求 4C8G,节点剩余不足则过滤
NodeName 检查 Pod 是否指定了 nodeName 直接指定节点
PodTopologySpread 确保 Pod 在拓扑域(如区域、节点)中均匀分布 高可用部署
TaintToleration 检查 Pod 是否能容忍节点的污点 专用节点、GPU 节点
NodeAffinity 检查节点标签是否满足 Pod 的节点亲和性规则 将 Pod 调度到特定区域

3.3.2 优选阶段(Scoring)

优选阶段对预选通过的节点进行打分,选出最优节点。每个优选策略会返回一个 0-100 的分数,最终加权求和:

最终分数 = Σ(策略分数 × 策略权重) / 总权重

常见的优选策略:

  • NodeResourcesBalancedAllocation:优先选择资源利用率均衡的节点(CPU 和内存使用率接近)。
  • NodeResourcesLeastAllocated:优先选择资源剩余最多的节点(负载分散)。
  • NodeResourcesMostAllocated:优先选择资源利用率最高的节点(资源集中)。
  • ImageLocality:优先选择已缓存 Pod 所需镜像的节点,减少镜像拉取时间。
  • InterPodAffinity:根据 Pod 间的亲和性/反亲和性打分。
注意: 默认调度器使用 LeastAllocated 策略,适合负载分散场景。如果集群资源紧张,可考虑切换为 MostAllocated 以提高资源利用率。ImageLocality 策略在镜像拉取成为瓶颈时尤为重要,后续章节会深入讲解。

3.4 绑定周期:将决策写入集群

调度周期结束后,调度器已经选定了目标节点。绑定周期的任务是将这个决策持久化:

  1. 假设(Assume):调度器先在缓存中假设 Pod 已被调度到该节点,更新缓存状态。
  2. 绑定(Bind):调度器通过 API Server 更新 Pod 的 spec.nodeName 字段。
  3. 确认(Reserve):Kubelet 监听到 Pod 被调度到本节点,开始拉取镜像并启动容器。
绑定周期关键点:
  • 异步绑定:调度器不会等待绑定完成再处理下一个 Pod,而是异步执行绑定操作,提高吞吐量。
  • 乐观锁定:绑定操作使用乐观锁(ResourceVersion),避免并发冲突。
  • 绑定失败处理:如果绑定失败(如节点已满),调度器会将 Pod 重新放回队列,并标记为调度失败。
调度周期与绑定周期完整流程 调度队列 PriorityQueue 预选(Filter) 过滤不可行节点 优选(Score) 打分选出最优节点 假设(Assume) 缓存中更新状态 绑定(Bind) 写入 NodeName Kubelet 确认 拉取镜像启动容器 调度周期 vs 绑定周期 • 调度周期:纯计算,不修改集群状态,只生成决策。 • 绑定周期:修改集群状态,将 Pod 与节点绑定。 • 调度周期失败 → Pod 重新入队;绑定周期失败 → Pod 重新调度。

3.5 调度失败与重试机制

Pod 调度可能因多种原因失败,调度器内置了完善的重试机制:

失败原因 处理方式 重试间隔
资源不足 进入 unschedulableQ,等待集群资源变化 事件触发
节点污点不匹配 进入 unschedulableQ,等待节点污点变化 事件触发
抢占失败 进入 backoffQ,指数退避 1s, 2s, 4s, 8s...
绑定失败 重新进入调度周期 立即重试(有限次数)
排查建议: 使用 kubectl describe pod <pod-name> 查看 Events 字段,可以快速定位调度失败原因。常见错误包括 0/4 nodes are available(资源不足)和 node(s) had taints(污点不匹配)。

3.6 本章小结

  • Pod 调度生命周期包括:入队 → 调度周期(预选+优选) → 绑定周期(假设+绑定) → Kubelet 确认。
  • 调度队列使用 PriorityQueue,包含 activeQ、backoffQ、unschedulableQ 三个子队列。
  • 调度周期通过预选过滤不可行节点,通过优选打分选出最优节点。
  • 绑定周期将调度决策持久化到 etcd,并通知 Kubelet 启动容器。
  • 调度失败时,Pod 会根据失败原因进入不同的队列等待重试。