调度策略与算法:默认调度策略、节点亲和性、Pod亲和性与反亲和性

Kubernetes 调度器(kube-scheduler)的核心职责是将待调度的 Pod 绑定到最合适的节点上。调度过程分为两个阶段:过滤(Predicates) 和 打分(Priorities)。本章深入剖析默认调度策略、节点亲和性(nodeAffinity)以及 Pod 亲和性/反亲和性(podAffinity / podAntiAffinity),帮助你在生产环境中精准控制 Pod 的放置位置。

1. 默认调度策略:过滤与打分机制

调度器首先通过一组过滤规则(Predicates)排除不满足条件的节点,然后对剩余节点进行打分(Priorities),最终选择得分最高的节点运行 Pod。

关键过滤策略(Predicates):
  • PodFitsResources: 检查节点剩余 CPU、内存是否满足 Pod 的 requests。
  • PodFitsHostPorts: 检查 Pod 请求的端口是否已被占用。
  • MatchNodeSelector: 检查节点标签是否匹配 Pod 的 nodeSelector。
  • NoDiskConflict: 检查卷挂载是否冲突。
  • CheckNodeCondition: 排除网络不可用、磁盘压力等异常节点。
关键打分策略(Priorities):
  • LeastRequestedPriority: 优先选择资源利用率低的节点,实现负载均衡。
  • BalancedResourceAllocation: 优先选择 CPU 和内存使用率最均衡的节点。
  • NodeAffinityPriority: 根据节点亲和性规则的权重进行加分。
  • ImageLocalityPriority: 优先选择已存在所需容器镜像的节点,减少拉取时间。
默认调度两阶段流程 待调度 Pod 阶段一:过滤(Predicates) 资源、端口、节点条件、卷冲突检查 阶段二:打分(Priorities) 资源均衡、亲和性权重、镜像本地性 绑定到最优节点 默认调度器可扩展:通过 Scheduler Framework 注入自定义过滤/打分插件

2. 节点亲和性(nodeAffinity)

节点亲和性是对 nodeSelector 的增强,支持更丰富的匹配表达式和优先级控制。它分为两种类型:

类型 语义 调度阶段 典型场景
requiredDuringSchedulingIgnoredDuringExecution 硬性要求:节点必须满足规则,否则 Pod 无法调度 过滤阶段 GPU 节点、合规区域限制
preferredDuringSchedulingIgnoredDuringExecution 软性偏好:尽量满足,不满足时仍可调度到其他节点 打分阶段 靠近缓存服务、成本优化
最佳实践: 使用 preferredDuringScheduling 时,务必设置 weight 字段(1-100),权重越高,调度器越倾向于满足该规则。
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: gpu-type
            operator: In
            values:
            - nvidia-tesla-v100
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - us-east-1a
  containers:
  - name: gpu-container
    image: nvidia/cuda:11.0-base

3. Pod 亲和性与反亲和性

Pod 亲和性/反亲和性允许你根据 已有 Pod 的标签 来决定新 Pod 的调度位置,而非仅依赖节点标签。这是实现微服务就近部署、故障域隔离的核心手段。

3.1 核心概念

概念 说明 拓扑键(topologyKey)
podAffinity 新 Pod 倾向于与满足标签条件的 Pod 运行在同一拓扑域 kubernetes.io/hostname(同一节点)
failure-domain.beta.kubernetes.io/zone(同一可用区)
podAntiAffinity 新 Pod 倾向于不与满足标签条件的 Pod 运行在同一拓扑域 同上,用于分散部署
required / preferred 与节点亲和性类似,分为硬性要求和软性偏好 —

3.2 典型配置示例

场景一:将 Web Pod 与 Redis Pod 调度到同一节点(降低延迟)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - redis
            topologyKey: kubernetes.io/hostname
      containers:
      - name: web
        image: nginx:latest

场景二:将同一服务的多个副本分散到不同节点(高可用)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 5
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - frontend
              topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:latest
性能警告: 在大型集群(数千节点)中使用 requiredDuringScheduling 的 Pod 反亲和性时,调度器需要遍历所有节点上的 Pod 标签,可能导致调度延迟显著增加。建议优先使用 preferredDuringScheduling 或缩小 topologyKey 范围。

4. 调度策略对比总结

策略 作用对象 匹配方式 典型用途 性能影响
nodeSelector 节点标签 精确键值匹配 简单硬件分类 低
nodeAffinity 节点标签 表达式匹配 + 权重 复杂节点选择、区域偏好 中
podAffinity Pod 标签 表达式匹配 + 拓扑键 服务就近部署、缓存亲和 中高
podAntiAffinity Pod 标签 表达式匹配 + 拓扑键 故障域隔离、分散部署 高(required 模式)
Pod 亲和性与反亲和性调度效果示意 Pod 亲和性(同节点) 节点 A Redis Web 节点 B (空闲) topologyKey: hostname Pod 反亲和性(分散节点) 节点 C Frontend-1 节点 D Frontend-2 topologyKey: hostname 调度决策逻辑 • 亲和性:调度器优先将 Web Pod 分配到已有 Redis Pod 的节点(节点 A) • 反亲和性:调度器确保同一 Deployment 的副本分布在不同的节点(节点 C、D) • topologyKey 决定“拓扑域”的粒度:hostname(节点级)、zone(可用区级)

5. 生产环境调度策略选择指南

  1. 简单硬件隔离: 使用 nodeSelector 或 nodeAffinity required 绑定 GPU、SSD 等特殊节点。
  2. 区域容灾与成本优化: 使用 nodeAffinity preferred 配合多可用区标签,优先调度到低成本区域。
  3. 微服务通信优化: 使用 podAffinity required 将频繁通信的服务(如 Web + Cache)调度到同一节点或同一可用区。
  4. 高可用与故障隔离: 使用 podAntiAffinity preferred 将同一服务的多个副本分散到不同节点或不同可用区。
  5. 避免调度热点: 对于大规模集群,反亲和性优先使用 preferred 模式,并合理设置 topologyKey 为 zone 而非 hostname,减少调度器压力。
调试命令: 使用 kubectl describe pod <pod-name> 查看调度事件;使用 kubectl get nodes --show-labels 检查节点标签;使用 kubectl get pods -o wide 确认 Pod 分布情况。