2. Kubernetes 调度基础:调度器工作原理、节点亲和性、Pod 亲和性与反亲和性

2.1 调度器工作原理

Kubernetes 调度器(kube-scheduler)是控制平面的核心组件之一,负责将待调度的 Pod 绑定到最合适的节点上。调度过程分为两个阶段:过滤(Predicates) 和 打分(Priorities)。

核心调度流程: Watch → 过滤 → 打分 → 绑定。调度器通过 watch 机制监听未调度的 Pod,依次执行过滤和打分,最终将 Pod 绑定到最优节点。
Kubernetes 调度器两阶段工作流程 过滤阶段 Predicates 打分阶段 Priorities 绑定阶段 Bind 常见过滤条件 • Pod 资源请求 • 节点污点容忍 • 节点选择器 • 端口冲突检查 常见打分策略 • 资源余量优先 • 镜像局部性 • 节点亲和性 • Pod 亲和性 绑定结果 写入 etcd
生产建议: 在 GitOps 流水线中,调度策略应作为 PodSpec 的一部分声明在 Git 仓库中。调度器根据这些声明自动选择节点,无需人工干预。

2.2 节点亲和性(Node Affinity)

节点亲和性允许你根据节点上的标签(Label)来约束 Pod 可以调度到哪些节点。它分为两种类型:

类型 语义 调度阶段 典型场景
requiredDuringSchedulingIgnoredDuringExecution 硬约束:必须满足条件才能调度 过滤阶段 GPU 节点、合规节点
preferredDuringSchedulingIgnoredDuringExecution 软约束:尽量满足,不满足也可调度 打分阶段 高性能节点、低延迟节点

节点亲和性使用 nodeSelectorTerms 和 matchExpressions 定义匹配规则,支持 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: gpu-type
            operator: In
            values:
            - nvidia-tesla
            - amd-mi250
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1a
  containers:
  - name: gpu-container
    image: nvidia/cuda:12.0-base
注意: 节点亲和性只影响 Pod 调度时的节点选择,不会影响已经运行的 Pod。如果节点标签在 Pod 运行后发生变化,已调度的 Pod 不会重新调度。

2.3 Pod 亲和性与反亲和性

Pod 亲和性与反亲和性根据节点上已经运行的 Pod 的标签来决定调度位置,而不是节点本身的标签。这用于控制 Pod 之间的分布关系。

类型 作用 拓扑键(topologyKey) 典型用例
Pod 亲和性(podAffinity) 将 Pod 调度到与特定 Pod 相同的拓扑域 kubernetes.io/hostname
topology.kubernetes.io/zone
缓存服务与计算服务同节点部署
Pod 反亲和性(podAntiAffinity) 避免 Pod 调度到与特定 Pod 相同的拓扑域 kubernetes.io/hostname
topology.kubernetes.io/zone
高可用应用跨节点/跨可用区部署

Pod 亲和性/反亲和性同样支持 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 两种模式。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-frontend
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
关键区别: 节点亲和性关注节点标签,Pod 亲和性关注 Pod 标签。在 GitOps 实践中,建议将亲和性规则作为应用配置的一部分,与 Helm Chart 或 Kustomize 一起版本化管理。

2.4 三种调度约束对比

特性 节点亲和性 Pod 亲和性 Pod 反亲和性
匹配对象 节点标签 Pod 标签 Pod 标签
调度目标 将 Pod 调度到特定节点 将 Pod 调度到已有特定 Pod 的拓扑域 将 Pod 调度到没有特定 Pod 的拓扑域
拓扑域概念 无(直接匹配节点) 需要 topologyKey 需要 topologyKey
性能影响 低(仅检查节点标签) 中(需要查询 Pod 分布) 中(需要查询 Pod 分布)
典型场景 GPU、SSD、合规节点 缓存与计算同节点 高可用、故障隔离

2.5 调度策略在 GitOps 中的实践

在 GitOps 工作流中,调度策略应遵循以下原则:

  • 声明式配置: 所有亲和性规则写在 Deployment/StatefulSet 的 spec.template.spec.affinity 中,存储在 Git 仓库。
  • 环境差异化: 通过 Helm values 或 Kustomize overlay 为不同环境(dev/staging/prod)设置不同的调度策略。
  • 节点标签管理: 节点标签通过自动化工具(如 Cluster API、Terraform)管理,确保标签与 Git 配置一致。
  • 调度策略测试: 在 CI 流水线中使用 kube-score 或 polaris 验证调度配置的正确性。
最佳实践: 优先使用 preferredDuringSchedulingIgnoredDuringExecution 作为默认策略,仅在关键场景(如 GPU 任务、合规要求)使用 requiredDuringSchedulingIgnoredDuringExecution,避免因节点标签缺失导致 Pod 无法调度。