GitOps流水线集成K8s调度优化同步窗口 - 第2节

Kubernetes 调度器工作原理与调度流程

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的 Node 上。调度器不负责创建 Pod,而是监听未调度的 Pod(spec.nodeName 为空),通过一系列调度算法选出目标节点,并将绑定结果写入 API Server。

调度器工作流程

调度过程分为两个阶段:过滤(Predicates / Filtering) 和 打分(Priorities / Scoring)。过滤阶段排除不满足条件的节点,打分阶段对剩余节点排序,选出最优节点。

核心调度流程: 调度器通过 Informer 机制监听 Pod 和 Node 变化,每次调度一个 Pod 时,先执行 Filtering 阶段,再执行 Scoring 阶段,最后将 Pod 与 Node 绑定。
  1. Pod 入队: 调度器通过 Informer 监听 API Server,发现未调度的 Pod 后将其加入调度队列。
  2. 过滤阶段(Filtering): 遍历所有 Node,应用预选策略(如资源充足、端口冲突、节点污点容忍等),生成候选节点列表。
  3. 打分阶段(Scoring): 对候选节点执行优先级函数(如资源利用率、Pod 亲和性、节点亲和性等),计算每个节点的综合得分。
  4. 绑定(Binding): 选择得分最高的节点,将 Pod 的 spec.nodeName 设置为该节点,并通过 API Server 写入 etcd。
  5. 异步优化(可选): 调度器支持抢占调度(Preemption),当 Pod 无法调度时,可以抢占低优先级 Pod 的资源。
调度队列: Kubernetes 1.23+ 使用三种队列(activeQ、backoffQ、unschedulableQ)管理 Pod 调度状态,避免无效重试。

调度器架构图

下图展示了调度器内部组件与调度流程的交互关系:

Kubernetes 调度器架构与调度流程 Kubernetes 调度器架构与调度流程 API Server 调度队列 (Queue) 过滤阶段 (Filtering) 打分阶段 (Scoring) 绑定 (Binding) Node 列表 候选节点 写入 etcd 调度器通过 Informer 监听 Pod/Node 变化,每次调度一个 Pod 时依次执行过滤、打分、绑定 过滤阶段排除不满足条件的节点,打分阶段对剩余节点排序,选出最优节点

NodeSelector:简单的节点选择器

nodeSelector 是 Kubernetes 提供的最简单的节点选择机制,通过 Pod 的 spec.nodeSelector 字段指定键值对,调度器只将 Pod 调度到包含所有指定标签的节点上。

使用方式

apiVersion: v1
kind: Pod
metadata:
  name: nginx-selector
spec:
  nodeSelector:
    disktype: ssd
  containers:
  - name: nginx
    image: nginx:1.25

上述 Pod 只会被调度到带有 disktype=ssd 标签的节点上。如果没有任何节点匹配,Pod 将保持 Pending 状态。

局限性: nodeSelector 只支持精确匹配(AND 逻辑),不支持多条件组合、范围匹配或软约束。对于复杂调度需求,应使用 NodeAffinity。

NodeAffinity:灵活的节点亲和性调度

NodeAffinity 是 nodeSelector 的增强版,支持更丰富的匹配规则和调度策略。NodeAffinity 分为两种类型:

类型 字段 行为 调度阶段
requiredDuringSchedulingIgnoredDuringExecution required 硬约束:必须满足规则才能调度,否则 Pod 保持 Pending 过滤阶段
preferredDuringSchedulingIgnoredDuringExecution preferred 软约束:调度器优先选择满足规则的节点,但不强制 打分阶段

NodeAffinity 匹配操作符

NodeAffinity 支持多种匹配操作符,满足不同场景的调度需求:

操作符 说明 示例
In 标签值在指定集合中 disktype In [ssd, nvme]
NotIn 标签值不在指定集合中 region NotIn [us-east-1]
Exists 标签键存在(不关心值) gpu-node Exists
DoesNotExist 标签键不存在 spot-instance DoesNotExist
Gt 标签值大于指定数值(字符串比较) memory-size Gt 32
Lt 标签值小于指定数值 cpu-cores Lt 8

NodeAffinity 配置示例

apiVersion: v1
kind: Pod
metadata:
  name: nginx-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-west-1a
            - us-west-1b
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
      - weight: 20
        preference:
          matchExpressions:
          - key: environment
            operator: In
            values:
            - production
  containers:
  - name: nginx
    image: nginx:1.25
调度逻辑: 上述 Pod 必须调度到 us-west-1a 或 us-west-1b 可用区(硬约束),优先选择带有 disktype=ssd 标签的节点(权重 80),其次考虑 environment=production 标签(权重 20)。

NodeSelector 与 NodeAffinity 对比

特性 NodeSelector NodeAffinity
匹配逻辑 精确键值对(AND) 多条件组合(AND/OR),支持 In/NotIn/Exists 等
软约束 不支持 支持(preferred)
权重 不支持 支持(weight 字段)
范围匹配 不支持 支持(Gt/Lt)
配置复杂度 低 中
适用场景 简单标签匹配 复杂调度策略、多维度约束

NodeAffinity 调度决策流程

下图展示了 NodeAffinity 在调度器中的决策路径:

NodeAffinity 调度决策流程 NodeAffinity 调度决策流程 Pod 携带 NodeAffinity 解析 required 规则 过滤不匹配节点 生成候选节点列表 解析 preferred 规则 加权打分 (Weighted) 选择得分最高节点 绑定 Pod 到 Node required 规则在过滤阶段执行,preferred 规则在打分阶段执行,权重影响最终节点选择

最佳实践与注意事项

  • 组合使用: 将 required 用于硬性约束(如可用区、GPU 节点),preferred 用于优化目标(如高性能磁盘、低负载节点)。
  • 权重设计: 权重范围 1-100,多个 preferred 规则通过权重累加影响最终得分,权重越高优先级越大。
  • 标签一致性: 确保 Node 标签与 Pod 的 NodeAffinity 规则一致,避免因标签缺失导致 Pod 无法调度。
  • 性能考虑: 过多的 NodeAffinity 规则会增加调度器计算开销,建议将规则数量控制在 10 条以内。
  • 与 Taint/Toleration 配合: NodeAffinity 控制 Pod 选择哪些节点,Taint/Toleration 控制哪些 Pod 可以进入节点,两者结合实现精细调度。
GitOps 场景提示: 在 GitOps 流水线中,NodeAffinity 规则通常定义在 Helm Chart 或 Kustomize 的 values 文件中,通过环境参数动态注入,实现多集群、多环境的差异化调度策略。