关于K8s调度策略(NodeSelector, Affinity, Anti-Affinity)
myluzh 发布于 阅读:14 Kubernetes
0x00 前言
在 Kubernetes 生产集群中,合理的调度策略是保障业务 高可用 (HA) 和 低延迟 (Low Latency) 的核心。调度逻辑主要分为“节点选择”与“邻里关系”两大类。
本文将涵盖 nodeSelector、Node Affinity(硬限制/软限制/NotIn)、以及 Pod Affinity/Anti-Affinity 的实现方式。
graph TD
%% 样式定义
classDef logic fill:#f9f9f9,stroke:#333,stroke-width:2px;
classDef node fill:#e1f5fe,stroke:#01579b;
classDef pod fill:#fff3e0,stroke:#e65100;
A[Pod 待调度] --> B{调度策略筛选}
subgraph NodeSelection [节点选择维度]
B --> C1[nodeSelector: 强匹配]:::logic
B --> C2[NodeAffinity: 灵活逻辑]:::logic
end
subgraph PodTopology [Pod 关系维度]
B --> D1[PodAffinity: 亲和/就近]:::logic
B --> D2[PodAntiAffinity: 反亲和/分散]:::logic
end
C1 & C2 --> E[Node 节点]:::node
D1 & D2 --> F[现有 Pod 拓扑]:::pod
0x01 基础调度:nodeSelector
nodeSelector 是最简单的强制性约束,仅支持 Exact Match(完全匹配)。
操作步骤
- 给节点打标签
root@k8s-master:~# kubectl label nodes node-01 disktype=ssd
- 配置 Pod 调度
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
nodeSelector:
disktype: ssd # 必须匹配,否则 Pod 无法调度 (Pending)
containers:
- name: nginx
image: nginx:1.21
0x02 进阶节点调度:Node Affinity
Node Affinity 提供了比 nodeSelector 更丰富的操作符(In, NotIn, Exists, Gt, Lt)以及软硬限制。
1. 硬限制 (Required)
requiredDuringSchedulingIgnoredDuringExecution:必须满足,否则 Pending。
2. 软限制 (Preferred)
preferredDuringSchedulingIgnoredDuringExecution:尽量满足。调度器会计算权重(Weight),分高者优选。
3. Node 反亲和实现 (NotIn)
通过 operator: NotIn 实现排除逻辑。
YAML 示例:
spec:
affinity:
nodeAffinity:
# 硬限制:必须在上海或北京
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/region
operator: In
values: ["shanghai", "beijing"]
# 软限制:尽量避开不稳定机型 (Node 反亲和)
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: status
operator: NotIn
values: ["unstable-vendor"]
0x03 拓扑感知调度:Pod Affinity & Anti-Affinity
这组策略不关注 Node 标签,而是关注 Node 上已经运行了什么 Pod。
1. 核心参数:topologyKey
用于定义“同一范围”的边界:
kubernetes.io/hostname: 同一台物理机/虚拟机。topology.kubernetes.io/zone: 同一个可用区(如:cn-hangzhou-g)。
2. Pod 正亲和 (PodAffinity)
场景:将 Web 应用和其缓存(Redis)部署在一起,减少网络开销。
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: redis
topologyKey: "kubernetes.io/hostname"
3. Pod 反亲和 (PodAntiAffinity) —— 生产高可用核心
场景:避免同一个服务的多个副本落在同一个节点上,防止单点故障。
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬限制:禁止同台
- labelSelector:
matchLabels:
app: web-server
topologyKey: "kubernetes.io/hostname"
0x04 总结与逻辑对比
| 概念 | 作用对象 | 逻辑类型 | 典型场景 |
|---|---|---|---|
| nodeSelector | Node Label | 硬限制 (In) | 简单固定的机器分配 |
| Node Affinity | Node Label | 硬/软 (In/NotIn) | 复杂硬件要求、避开特定节点 |
| Pod Affinity | Pod Label | 硬/软 | 业务就近部署,减少内网时延 |
| Pod Anti-Affinity | Pod Label | 硬/软 | 生产环境高可用,副本分散 |
运维避坑指南
- IgnoredDuringExecution:所有的亲和性规则目前都只在“调度时”生效。如果 Pod 运行中 Node 标签变了,Pod 不会被自动驱逐。
- 计算开销:
PodAffinity需要扫描集群内所有 Pod 的标签,在超过 500 个节点的大型集群中,大量使用会导致调度器明显变慢。 - 互斥检查:如果你同时定义了 Pod 正亲和与反亲和,且逻辑冲突,Pod 将永远处于 Pending 状态。