4. 节点亲和性调度:nodeSelector、nodeAffinity硬策略、nodeAffinity软策略、权重配置
在Kubernetes集群中,Pod调度到哪个节点并非完全随机。节点亲和性(Node Affinity)是调度器将Pod绑定到特定节点的一组规则,它比简单的 nodeSelector 更灵活、表达能力更强。本章从最基础的 nodeSelector 出发,逐步深入到 nodeAffinity 的硬策略(required)、软策略(preferred)以及权重配置,帮助你精准控制Pod的放置位置。
4.1 基础选择器:nodeSelector
nodeSelector 是Kubernetes最早提供的节点选择机制,它通过Pod的 spec.nodeSelector 字段指定一组键值对标签,调度器只将Pod调度到包含所有这些标签的节点上。这是一种“与(AND)”逻辑——所有条件必须同时满足。
适用场景: 简单、静态的节点选择需求,例如将GPU工作负载调度到带有
gpu=true 标签的节点。
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
nodeSelector:
gpu: "true" # 节点必须包含标签 gpu=true
containers:
- name: cuda-container
image: nvidia/cuda:11.0-base
| 特性 | nodeSelector | nodeAffinity |
|---|---|---|
| 表达式能力 | 仅支持精确键值对匹配(=) | 支持 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符 |
| 逻辑组合 | 多个条件之间为 AND 关系 | 支持 AND(同一规则内)和 OR(多个 matchExpressions) |
| 软/硬策略 | 硬性要求(不满足则不调度) | 支持硬策略(required)和软策略(preferred) |
| 权重 | 不支持 | 软策略支持权重(weight 1-100) |
4.2 nodeAffinity 硬策略(requiredDuringSchedulingIgnoredDuringExecution)
硬策略要求Pod必须调度到满足条件的节点上,否则Pod将处于 Pending 状态。其名称中的 IgnoredDuringExecution 表示:即使Pod运行后节点标签发生变化,已经运行的Pod也不会被驱逐。
apiVersion: v1
kind: Pod
metadata:
name: ssd-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk-type
operator: In
values:
- ssd
- nvme
containers:
- name: app
image: nginx:1.21
关键点:
nodeSelectorTerms 列表中的多个 matchExpressions 之间是 OR 关系(满足任一即可);而同一个 matchExpressions 内的多个条件之间是 AND 关系(必须全部满足)。
4.3 nodeAffinity 软策略(preferredDuringSchedulingIgnoredDuringExecution)
软策略是“尽力而为”的调度偏好。调度器会优先选择满足条件的节点,但如果找不到符合条件的节点,Pod仍然可以被调度到其他节点上。软策略必须配合 weight 字段使用,权重值范围为 1-100,权重越高,调度器越倾向于选择该节点。
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1
- weight: 20
preference:
matchExpressions:
- key: instance-type
operator: In
values:
- c5.large
containers:
- name: app
image: nginx:1.21
注意: 软策略的权重是 相对值,调度器会计算每个候选节点的总得分(所有匹配的软策略权重之和),得分最高的节点被选中。如果多个节点得分相同,调度器会随机选择一个。
4.4 权重配置与调度决策流程
当同时使用多个软策略时,权重决定了调度器的偏好优先级。下面的SVG图展示了调度器如何综合硬策略和软策略做出最终决策。
4.5 多策略组合实战
在实际生产环境中,硬策略和软策略经常组合使用。例如:要求Pod必须运行在SSD节点上(硬策略),同时优先选择低负载的节点(软策略)。
apiVersion: v1
kind: Pod
metadata:
name: production-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk-type
operator: In
values:
- ssd
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 70
preference:
matchExpressions:
- key: node-load
operator: NotIn
values:
- high
- weight: 30
preference:
matchExpressions:
- key: zone
operator: In
values:
- zone-a
containers:
- name: app
image: myapp:latest
最佳实践:
- 硬策略用于强制约束(如合规、安全、硬件要求),数量不宜过多(建议 ≤ 3 个)。
- 软策略用于性能优化或成本控制,权重值应体现业务优先级差异(如 80 vs 20 比 50 vs 40 更清晰)。
- 避免在软策略中使用
operator: Exists或DoesNotExist这类宽泛条件,否则可能导致调度结果不可预测。
4.6 操作符对比与选择
| 操作符 | 含义 | 示例 | 适用场景 |
|---|---|---|---|
In |
标签值在给定集合中 | zone In [us-east-1, us-west-2] |
多区域部署,指定可用区 |
NotIn |
标签值不在给定集合中 | node-type NotIn [spot] |
排除竞价实例节点 |
Exists |
节点存在该标签(不关心值) | gpu Exists |
只要节点有GPU标签即可 |
DoesNotExist |
节点不存在该标签 | maintenance DoesNotExist |
排除维护中的节点 |
Gt |
标签值大于指定数值(字符串比较) | memory Gt 32 |
内存大于32GB的节点 |
Lt |
标签值小于指定数值 | cpu-cores Lt 8 |
CPU核心数小于8的节点 |
性能提示: 使用
Gt 和 Lt 操作符时,标签值会被解析为数值进行比较。如果标签值不是纯数字(如 32GB),比较结果可能不符合预期。建议在节点标签中使用纯数字表示资源量。
4.7 常见问题与排查
- Pod一直Pending: 检查硬策略是否过于严格,使用
kubectl describe pod <pod-name>查看调度事件,确认是否有0/3 nodes are available的提示。 - 软策略未生效: 确认权重值是否在 1-100 范围内,且
preference字段下的matchExpressions语法正确。 - 标签拼写错误: 使用
kubectl get nodes --show-labels验证节点标签的实际键值对。 - 多个nodeSelectorTerms的OR逻辑混淆: 记住:
nodeSelectorTerms列表项之间是 OR,matchExpressions列表项之间是 AND。