2、调度策略基础:节点选择器(nodeSelector)、亲和性与反亲和性概念
Kubernetes 调度器(kube-scheduler)在将 Pod 绑定到合适节点时,除了默认的“资源足够”与“节点未污染”等硬性条件外,还提供了一系列节点选择与约束机制,用于控制 Pod 在集群中的分布位置。这些机制从简单到复杂依次为:nodeSelector、节点亲和性(nodeAffinity)、Pod 间亲和性(podAffinity)与 Pod 间反亲和性(podAntiAffinity)。
理解这三类策略的表达能力与生效阶段,是后续学习拓扑分布约束与抢占事件复核的基础。
2.1 节点选择器(nodeSelector)—— 最简的标签匹配
nodeSelector 是 Kubernetes 最早提供的节点选择方式,属于硬性约束(required)。它在 Pod 的 spec 中指定一个键值对映射,调度器只会将 Pod 调度到包含所有指定标签的节点上。
关键特征:
- 仅支持精确匹配(key=value),不支持集合运算(In/NotIn/Exists)。
- 多个标签之间是逻辑与(AND)关系,必须全部满足。
- 如果集群中没有节点满足所有标签,Pod 将一直处于
Pending状态。
| 特性 | nodeSelector | 适用场景 |
|---|---|---|
| 匹配方式 | 精确等值(key=value) | 简单环境隔离(如:disk=ssd) |
| 逻辑关系 | AND(所有条件必须满足) | GPU 节点绑定(gpu=nvidia) |
| 灵活性 | 低,不支持运算符 | 快速原型或小型集群 |
apiVersion: v1
kind: Pod
metadata:
name: ssd-pod
spec:
nodeSelector:
disk: ssd # 仅调度到标签 disk=ssd 的节点
containers:
- name: app
image: nginx
2.2 亲和性与反亲和性—— 更丰富的表达力
亲和性与反亲和性在 nodeSelector 的基础上引入了运算符(In、NotIn、Exists、DoesNotExist、Gt、Lt)和软约束/硬约束(requiredDuringSchedulingIgnoredDuringExecution vs preferredDuringSchedulingIgnoredDuringExecution)的概念,使调度策略更加灵活。
根据作用对象的不同,亲和性分为两类:
- 节点亲和性(nodeAffinity):控制 Pod 与节点标签的关系。
- Pod 间亲和性(podAffinity / podAntiAffinity):控制 Pod 与其他 Pod 的拓扑位置关系。
记忆口诀:“节点亲和看节点,Pod 亲和看邻居;硬约束必须满足,软约束尽量满足。”
2.3 节点亲和性(nodeAffinity)详解
节点亲和性允许使用表达式来匹配节点标签,并支持权重(weight)机制。其结构分为两个子字段:
| 字段 | 类型 | 说明 |
|---|---|---|
requiredDuringSchedulingIgnoredDuringExecution |
硬约束 | 调度时必须满足,否则 Pod 不调度;运行期间节点标签变化不影响已运行 Pod |
preferredDuringSchedulingIgnoredDuringExecution |
软约束 | 调度时尽量满足,不满足仍可调度到其他节点;可设置 weight(1-100) |
apiVersion: v1
kind: Pod
metadata:
name: node-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: instance-type
operator: In
values:
- c5.large
containers:
- name: app
image: nginx
注意:
nodeSelectorTerms 下多个 matchExpressions 之间是OR关系(满足任一即可);而单个 matchExpressions 内的多个表达式是AND关系(必须全部满足)。这一逻辑与 nodeSelector 的纯 AND 不同,容易混淆。
2.4 Pod 间亲和性与反亲和性
Pod 间亲和性用于控制同一 Pod 与其他 Pod 在拓扑上的相对位置。它依赖 topologyKey 来定义“拓扑域”的粒度(如 kubernetes.io/hostname 表示节点级别,topology.kubernetes.io/zone 表示可用区级别)。
| 类型 | 作用 | 典型场景 |
|---|---|---|
| podAffinity | 将 Pod 调度到靠近某些 Pod 的拓扑域 | Web 与缓存同节点/同可用区,降低延迟 |
| podAntiAffinity | 将 Pod 调度到远离某些 Pod 的拓扑域 | 避免同一应用多个副本部署在同一节点/可用区 |
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-anti-affinity
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
关键设计原则:
- Pod 间亲和性/反亲和性只对同一命名空间内的 Pod 生效(除非设置
namespaceSelector)。 topologyKey不能为空,且对于反亲和性,topologyKey不能是kubernetes.io/hostname以外的任意标签(除非集群配置了MatchLabelKeys等高级特性)。- 反亲和性如果设置为
required且副本数超过拓扑域数量,会导致部分 Pod 无法调度(Pending)。
2.5 三种策略对比总结
| 维度 | nodeSelector | nodeAffinity | podAffinity / podAntiAffinity |
|---|---|---|---|
| 作用对象 | 节点标签 | 节点标签 | 其他 Pod 的标签 |
| 匹配能力 | 精确等值 | In/NotIn/Exists/DoesNotExist/Gt/Lt | In/NotIn/Exists/DoesNotExist |
| 约束类型 | 仅硬约束 | 硬约束 + 软约束(带权重) | 硬约束 + 软约束(带权重) |
| 拓扑感知 | 无 | 无 | 依赖 topologyKey 定义拓扑域 |
| 典型用途 | 快速绑定专用节点 | 按实例类型、可用区精细调度 | 高可用分散、缓存就近部署 |
最佳实践建议:
- 优先使用 nodeAffinity 替代
nodeSelector,以获得更灵活的表达式支持。 - 对于高可用应用,务必使用
podAntiAffinity并设置topologyKey: kubernetes.io/hostname,避免同一应用多个副本落在同一节点。 - 软约束的
weight值建议差异化设置(如 80/20),避免多个软约束权重相同导致调度器无法区分优先级。 - 避免在
requiredDuringScheduling中使用过于严格的 Pod 间反亲和性,否则可能导致副本数无法满足调度需求。