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 |
| 分层设计 | 基础设施层、拓扑层、功能层标签分离 | 所有标签混在一个层级 |
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 亲和性时的完整决策路径:
2.5 节点亲和性 vs 节点反亲和性
Kubernetes 同时提供 nodeAffinity(节点亲和性)和 nodeAntiAffinity(节点反亲和性)。前者吸引 Pod 到某类节点,后者排斥 Pod 离开某类节点。两者配合可实现高可用分布和故障域隔离。
| 特性 | nodeAffinity | nodeAntiAffinity |
|---|---|---|
| 目标 | 将 Pod 调度到特定节点 | 将 Pod 分散到不同节点 |
| 典型用途 | GPU 节点、SSD 节点、合规节点 | 避免单点故障、跨可用区分布 |
| 操作符 | In、NotIn、Exists、Gt、Lt | In、NotIn、Exists、DoesNotExist |
| 软/硬约束 | 两者均支持 | 两者均支持 |
preferredDuringScheduling 使用,避免硬约束导致调度死锁。
2.6 节点标签设计实战原则
良好的节点标签设计是亲和性策略有效运行的前提。以下是一套经过生产验证的分层标签体系:
- 基础设施层:
node.kubernetes.io/instance-type(实例规格)、node.kubernetes.io/os(操作系统) - 拓扑层:
topology.kubernetes.io/region(区域)、topology.kubernetes.io/zone(可用区) - 硬件能力层:
node.kubernetes.io/gpu(GPU 型号)、disk-type(磁盘类型) - 运维管理层:
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 的键值对转换为 requiredDuringSchedulingIgnoredDuringExecution 下的 matchExpressions 即可。