2. 节点亲和性概念:nodeSelector、nodeAffinity 与节点标签设计

节点亲和性(Node Affinity)是 Kubernetes 调度器将 Pod 绑定到特定节点的一组策略机制。它通过节点标签(Node Labels)作为匹配依据,控制 Pod 可以或应该被调度到哪些节点上。本章深入剖析三种核心实现方式:nodeSelector、nodeAffinity 以及节点标签的设计原则。

2.1 节点标签:亲和性的基础

节点标签是键值对(Key-Value)形式的元数据,附着在 Node 对象上。调度器通过标签选择器(Label Selector)匹配 Pod 与节点的关系。标签设计直接影响调度灵活性、运维效率和集群可扩展性。

设计维度 推荐做法 避免做法
命名空间 使用前缀如 node.kubernetes.io/、topology.kubernetes.io/ 无前缀的随意字符串,易冲突
语义清晰 node.kubernetes.io/instance-type: gpu type: a 含义模糊
值范围可控 枚举值如 ssd、hdd、nvme 自由文本如 fast-disk-2024
分层设计 基础设施层、拓扑层、功能层标签分离 所有标签混在一个层级
最佳实践: 节点标签应作为“节点属性”而非“Pod 需求”来设计。例如标记节点拥有 GPU、SSD 或特定区域,而不是标记“这个节点运行 Web 应用”。

2.2 nodeSelector:简单直接的节点选择

nodeSelector 是 Pod 规范中最简单的节点约束字段。它使用 matchLabels 精确匹配节点标签,所有条件必须同时满足(AND 逻辑)。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  nodeSelector:
    node.kubernetes.io/instance-type: gpu
    topology.kubernetes.io/zone: us-east-1a
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.0
  • 优点: 语法极简,适合快速固定调度目标。
  • 缺点: 仅支持精确相等匹配,不支持 In、NotIn、Exists 等操作符;无法表达“尽量调度到某类节点”的软约束。
  • 适用场景: 测试环境、明确硬件绑定(如 GPU 节点)、合规性强制隔离。

2.3 nodeAffinity:丰富灵活的亲和性表达

nodeAffinity 是 nodeSelector 的进化版,属于 Pod 的 affinity 字段。它支持两种语义:requiredDuringSchedulingIgnoredDuringExecution(硬约束)和 preferredDuringSchedulingIgnoredDuringExecution(软约束)。

类型 语义 调度行为 执行阶段
required 必须满足,否则 Pod 无法调度 强制过滤节点 调度时(运行后不重新检查)
preferred 尽量满足,不满足则调度到其他节点 加权排序节点 调度时(运行后不重新检查)

nodeAffinity 支持丰富的匹配操作符:

  • In:标签值在给定集合中
  • NotIn:标签值不在给定集合中
  • Exists:标签键存在(忽略值)
  • DoesNotExist:标签键不存在
  • Gt / Lt:标签值大于/小于给定数值(仅适用于数值型标签)
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: node.kubernetes.io/instance-type
            operator: In
            values:
            - gpu
      - weight: 20
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
关键区别: nodeSelector 是扁平精确匹配;nodeAffinity 支持多条件、多操作符、软硬分离,是生产环境的首选。

2.4 节点亲和性工作流程

下图展示了调度器在处理 Pod 亲和性时的完整决策路径:

节点亲和性调度决策流程 节点亲和性调度决策流程 Pod 创建请求 检查 nodeSelector(精确匹配) 检查 nodeAffinity(硬约束) 过滤:保留满足硬约束的节点 加权排序:软约束 + 其他优先级 选定最优节点

2.5 节点亲和性 vs 节点反亲和性

Kubernetes 同时提供 nodeAffinity(节点亲和性)和 nodeAntiAffinity(节点反亲和性)。前者吸引 Pod 到某类节点,后者排斥 Pod 离开某类节点。两者配合可实现高可用分布和故障域隔离。

特性 nodeAffinity nodeAntiAffinity
目标 将 Pod 调度到特定节点 将 Pod 分散到不同节点
典型用途 GPU 节点、SSD 节点、合规节点 避免单点故障、跨可用区分布
操作符 In、NotIn、Exists、Gt、Lt In、NotIn、Exists、DoesNotExist
软/硬约束 两者均支持 两者均支持
注意: 节点反亲和性在集群节点数较少时可能导致 Pod 无法调度。建议配合 preferredDuringScheduling 使用,避免硬约束导致调度死锁。

2.6 节点标签设计实战原则

良好的节点标签设计是亲和性策略有效运行的前提。以下是一套经过生产验证的分层标签体系:

  1. 基础设施层: node.kubernetes.io/instance-type(实例规格)、node.kubernetes.io/os(操作系统)
  2. 拓扑层: topology.kubernetes.io/region(区域)、topology.kubernetes.io/zone(可用区)
  3. 硬件能力层: node.kubernetes.io/gpu(GPU 型号)、disk-type(磁盘类型)
  4. 运维管理层: node.kubernetes.io/taint(污点标记)、maintenance-window(维护窗口)

标签命名应遵循 前缀 + 语义键 + 枚举值 的规范,避免使用动态值(如 Pod 名称、时间戳)。

2.7 节点亲和性 vs nodeSelector 对比总结

对比维度 nodeSelector nodeAffinity
匹配能力 仅精确相等(=) In、NotIn、Exists、Gt、Lt
软约束支持 不支持 支持(preferred)
多条件组合 AND(所有条件必须满足) AND/OR(通过 nodeSelectorTerms 和 matchExpressions 组合)
可读性 简单直观 稍复杂但灵活
生产推荐 仅用于快速原型或简单场景 所有生产环境首选
核心结论: nodeSelector 是 nodeAffinity 的子集。从 Kubernetes v1.2 开始,官方推荐使用 nodeAffinity 替代 nodeSelector。迁移时只需将 nodeSelector 的键值对转换为 requiredDuringSchedulingIgnoredDuringExecution 下的 matchExpressions 即可。