4. 调度器与资源分配:调度流程、节点资源计算、调度策略与亲和性、调度失败常见原因
4.1 调度器核心工作流程
Kubernetes 调度器(kube-scheduler)负责将待调度的 Pod 绑定到最合适的节点上。整个调度过程分为两个阶段:过滤(Predicates) 和 打分(Priorities)。
- 过滤阶段:遍历所有节点,剔除不满足 Pod 资源请求、端口冲突、污点容忍、节点选择器等硬性条件的节点,得到候选节点列表。
- 打分阶段:对候选节点按资源利用率、亲和性规则、拓扑分布等策略进行评分,选出最优节点。
- 绑定阶段:将 Pod 与选定节点绑定,更新 etcd 中的绑定记录。
性能瓶颈提示: 当集群规模超过 1000 节点时,过滤/打分阶段的循环次数呈线性增长,调度吞吐量可能下降。建议启用调度器性能配置(
percentageOfNodesToScore)来限制打分节点比例。
4.2 节点资源计算与可分配资源
调度器在过滤阶段会计算节点上的可分配资源(Allocatable),而非节点总容量。可分配资源的计算公式为:
Allocatable = Node Capacity - Reserved - Eviction Threshold
其中 Reserved 包括 kube-reserved(系统组件预留)和 system-reserved(OS 守护进程预留)。
| 资源类型 | 说明 | 典型预留比例 |
|---|---|---|
| kube-reserved | kubelet、容器运行时、操作系统守护进程 | CPU 6% / 内存 20% |
| system-reserved | sshd、systemd 等系统进程 | CPU 5% / 内存 10% |
| eviction-hard | 节点压力驱逐阈值 | 内存 100Mi ~ 500Mi |
容量调优要点: 使用
kubectl describe node 查看 Allocatable 字段,确认实际可调度资源。如果节点 CPU 利用率长期低于 60% 但 Pod 调度失败,很可能是预留比例过高或资源碎片导致。
4.3 调度策略与亲和性
4.3.1 节点亲和性(Node Affinity)
节点亲和性分为两种:
- requiredDuringSchedulingIgnoredDuringExecution:硬性约束,调度时必须满足,类似
nodeSelector的增强版。 - preferredDuringSchedulingIgnoredDuringExecution:软性约束,调度时尽量满足,不满足仍可调度。
4.3.2 Pod 间亲和性与反亲和性
用于控制 Pod 之间的拓扑分布:
- PodAffinity:将相关 Pod 调度到同一拓扑域(如同一节点、同一可用区),降低网络延迟。
- PodAntiAffinity:将 Pod 分散到不同拓扑域,提高可用性。
| 策略类型 | 调度阶段 | 典型场景 | 性能影响 |
|---|---|---|---|
| required 亲和性 | 过滤阶段 | GPU Pod 必须调度到 GPU 节点 | 减少候选节点数,加速调度 |
| preferred 亲和性 | 打分阶段 | 优先将同服务 Pod 调度到同一节点 | 增加打分计算量 |
| PodAntiAffinity required | 过滤阶段 | 关键服务 Pod 分散到不同节点 | 可能大幅减少候选节点 |
常见误区: 过度使用
requiredDuringScheduling 反亲和性可能导致调度器找不到足够节点,尤其在节点数较少的小集群中。建议优先使用 preferred 软约束。
4.4 调度失败常见原因与排查
调度失败是容量问题的直接体现。以下是最常见的失败原因及排查方法:
| 失败原因 | 调度器日志关键词 | 典型根因 | 解决方向 |
|---|---|---|---|
| 资源不足 | Insufficient cpu / Insufficient memory |
节点可分配资源小于 Pod 请求 | 扩容节点 / 调整 Pod Request / 降低预留 |
| 端口冲突 | Pod port conflicts with an existing pod on node |
HostPort 被占用 | 使用 Service 代替 HostPort / 调整端口 |
| 污点不容忍 | node(s) had taints that the pod didn't tolerate |
节点有 NoSchedule 污点 | 添加对应容忍 / 移除污点 |
| 节点选择器不匹配 | node(s) didn't match node selector |
Pod 的 nodeSelector 无匹配节点 | 检查节点标签 / 放宽选择条件 |
| 亲和性不满足 | node(s) didn't match pod affinity/anti-affinity |
反亲和性导致无可用节点 | 改为 preferred / 增加节点 |
| 存储卷挂载冲突 | node(s) didn't find available persistent volumes to bind |
PV 与节点拓扑不匹配 | 使用拓扑感知调度 / 调整 PV 分布 |
快速排查命令:
kubectl describe pod <pod-name> 查看 Events 字段中的调度失败原因。kubectl get events --field-selector reason=FailedScheduling 查看集群级调度失败事件。
4.5 调度器性能瓶颈与调优方向
当集群规模较大或调度请求频繁时,调度器本身可能成为瓶颈。以下调优方向可提升调度吞吐量:
- 调整
percentageOfNodesToScore:默认 50%,大集群可降低到 30% 以减少打分节点数。 - 启用调度器缓存:避免每次调度都从 API Server 拉取全量节点信息。
- 使用调度器扩展(Scheduler Extender):将自定义过滤/打分逻辑外置,减少主调度器负载。
- 多调度器部署:为不同工作负载部署独立的调度器实例,隔离资源竞争。
容量调优核心思路: 调度失败不一定是节点不够,更多时候是资源碎片、预留过高或亲和性约束过严导致。先分析调度失败事件,再针对性调整资源请求或调度策略,往往比直接扩容更有效。