2. Kubernetes 调度基础:调度器工作原理、调度流程、节点选择与亲和性

2.1 调度器核心职责与架构

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。其本质是一个资源匹配与约束满足引擎,在集群资源碎片化、节点故障、拓扑约束等复杂场景下做出最优决策。

组件 职责 关键特性
kube-scheduler 监听未调度的 Pod,执行调度算法,写入绑定记录 可插拔调度框架,支持多调度器共存
调度队列 按优先级、抢占、重试策略管理待调度 Pod PriorityQueue + 背压机制
调度框架 定义扩展点(Filter/Score/Normalize/Reserve/Permit) v1.19+ 稳定,支持自定义插件
Cache 缓存集群 Node 与 Pod 快照,减少 API Server 压力 增量更新,一致性校验
调度器可观测性要点: 生产环境中建议开启 --v=4 日志级别,并通过 /metrics 端点监控 scheduler_pod_scheduling_duration_seconds 和 scheduler_queue_incoming_pods_total 指标,快速定位调度瓶颈。

2.2 调度流程:从 Pod 创建到绑定

调度流程分为两个阶段:过滤(Filtering) 和 打分(Scoring)。过滤阶段选出所有满足 Pod 资源请求、亲和性、污点容忍等硬约束的 Node;打分阶段对候选 Node 按优先级排序,最终选择最优节点。

Kubernetes 调度器两阶段流程 阶段一:过滤(Filtering) 硬约束检查,筛选可行 Node 资源请求检查 NodeSelector NodeAffinity TaintToleration 候选 Node 列表 阶段二:打分(Scoring) 软约束评分,选择最优 Node 资源利用率 PodAffinity 节点负载均衡 自定义评分插件 调度决策输出 最优 Node 选定 写入 Binding 记录 触发 Pod 启动
调度流程关键步骤(按顺序):
  1. PreFilter: 检查 Pod 的调度周期、抢占策略,执行 Pod 级别的预过滤。
  2. Filter: 并行执行所有过滤插件,剔除不满足硬约束的 Node。
  3. PostFilter: 若无可行 Node,触发抢占逻辑或标记调度失败。
  4. PreScore: 运行评分前的预处理,如计算 Pod 间亲和性缓存。
  5. Score: 对每个候选 Node 打分(0-100),支持加权组合。
  6. NormalizeScore: 对分数进行归一化处理,确保插件间分数可比。
  7. Reserve: 在 Cache 中预留资源,防止并发调度冲突。
  8. Permit: 等待外部准入条件(如资源配额、多调度器协调)。
  9. Bind: 写入 API Server 的 Binding 对象,完成调度。

2.3 节点选择机制:NodeSelector 与 NodeName

节点选择是调度器最基础的硬约束机制,通过标签匹配直接限定 Pod 可调度的节点范围。

机制 定义方式 匹配逻辑 适用场景
NodeName spec.nodeName 精确匹配节点名称,跳过调度器 调试、DaemonSet 固定节点
NodeSelector spec.nodeSelector 键值对精确匹配(AND 逻辑) 简单环境隔离(如 GPU 节点)
NodeAffinity(required) spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 支持 In/NotIn/Exists/DoesNotExist/Gt/Lt 操作符 复杂标签匹配,多条件组合
# NodeSelector 示例:仅调度到 GPU 节点
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  nodeSelector:
    accelerator: nvidia-tesla-v100
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.0-base
NodeSelector 局限性: 仅支持精确键值对匹配,无法表达“不在某组节点上”或“标签值大于某个数”等语义。生产环境建议优先使用 NodeAffinity 替代 NodeSelector,以获得更丰富的匹配操作符。

2.4 节点亲和性(NodeAffinity)

节点亲和性分为 required(硬约束) 和 preferred(软约束) 两种类型。硬约束在过滤阶段执行,不满足则 Pod 无法调度;软约束在打分阶段执行,权重越高越优先选择。

NodeAffinity 两种约束类型对比 requiredDuringScheduling 硬约束 · 过滤阶段执行 matchExpressions: [In, NotIn, Exists, ...] 所有条件必须满足(AND) 不满足 → Pod 无法调度 适用于安全隔离、合规要求 示例:必须调度到 SSD 节点 disk-type: ssd preferredDuringScheduling 软约束 · 打分阶段执行 weight: 1-100 + matchExpressions 满足条件增加权重分数 不满足 → 仍可调度到其他节点 适用于性能优化、成本控制 示例:优先选择可用区 A topology.kubernetes.io/zone: us-east-1a
# NodeAffinity 完整示例:硬约束 + 软约束组合
apiVersion: v1
kind: Pod
metadata:
  name: affinity-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1a
            - us-east-1b
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: instance-type
            operator: In
            values:
            - c5.2xlarge
      - weight: 20
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
  containers:
  - name: app
    image: nginx:latest
生产最佳实践: 将关键约束(如合规、安全)设为 required,将性能优化(如实例类型、磁盘类型)设为 preferred 并合理分配权重。权重值建议控制在 1-100 之间,避免极端值导致调度倾斜。

2.5 Pod 间亲和性与反亲和性

Pod 间亲和性(PodAffinity)与反亲和性(PodAntiAffinity)控制 Pod 与集群中其他 Pod 的相对位置关系,常用于微服务就近部署、故障域隔离等场景。

类型 语义 拓扑键(topologyKey) 典型场景
PodAffinity Pod 倾向于与目标 Pod 部署在同一拓扑域 kubernetes.io/hostname、topology.kubernetes.io/zone 缓存与计算节点就近部署,降低延迟
PodAntiAffinity Pod 倾向于与目标 Pod 分散在不同拓扑域 kubernetes.io/hostname、topology.kubernetes.io/zone 高可用部署,避免单点故障
# PodAntiAffinity 示例:确保同一应用的两个副本不在同一节点
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:1.25
反亲和性性能警告: requiredDuringScheduling 的反亲和性会显著增加调度器计算开销,当集群规模超过 1000 节点时,建议改用 preferredDuringScheduling 或通过拓扑分布约束(TopologySpreadConstraints)替代,避免调度器性能退化。

2.6 调度器扩展:自定义调度器与调度框架插件

Kubernetes 支持多调度器共存和调度框架插件扩展,满足 GitOps 场景下的特殊调度需求(如金丝雀发布、流量感知调度)。

  • 多调度器: 通过 spec.schedulerName 指定自定义调度器,实现不同工作负载使用不同调度策略。
  • 调度框架插件: 实现 FilterPlugin、ScorePlugin、BindPlugin 等接口,注入自定义逻辑。
  • GitOps 集成: 在 ArgoCD/Flux 的 Application 中通过 spec.syncPolicy 控制调度策略的灰度发布,结合 preferredDuringScheduling 实现渐进式调度。
# 自定义调度器声明示例
apiVersion: v1
kind: Pod
metadata:
  name: custom-scheduler-pod
spec:
  schedulerName: my-custom-scheduler
  containers:
  - name: app
    image: nginx:latest
GitOps 调度优化要点:
  • 使用 preferredDuringScheduling 实现金丝雀节点的软偏好,避免硬约束导致调度失败。
  • 结合 topologySpreadConstraints 实现跨可用区的均匀分布,提升回滚后的快速恢复能力。
  • 在调度器插件中注入 Prometheus 指标,监控调度延迟与失败率,为 GitOps 自动化回滚提供数据支撑。