第九篇:《调度策略:nodeSelector、亲和性、污点与容忍度》
Kubernetes 调度器负责将 Pod 分配到合适的节点。默认调度策略基于资源请求和节点可用资源,但有时你需要更精细的控制:例如将数据库 Pod 调度到 SSD 节点,或将特殊服务调度到特定区域。本文介绍调度相关的四种策略:nodeSelector、节点亲和性(Node Affinity)、Pod 亲和性与反亲和性,以及污点(Taint)与容忍度(Toleration)。掌握这些技巧,你可以实现复杂的生产级调度需求。
一、nodeSelector:最简单的节点选择
通过给节点打标签,然后在 Pod 中指定 nodeSelector,Pod 将只调度到匹配标签的节点。
1.1 给节点打标签
kubectl label node node1 disktype=ssd
kubectl label node node2 disktype=hdd
1.2 Pod 中使用 nodeSelector
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
nodeSelector:
disktype: ssd
containers:
- name: nginx
image: nginx
如果没有节点具有 disktype=ssd,Pod 将保持 Pending。
1.3 查看节点标签
kubectl get nodes --show-labels
二、节点亲和性(Node Affinity)
nodeSelector 只能做“硬约束”(必须满足),而节点亲和性支持:
硬约束(required):必须满足,否则不调度。
软约束(preferred):优先满足,但如果没有匹配节点,也可以调度到其他节点。
支持 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符。
2.1 硬约束示例
apiVersion: v1
kind: Pod
metadata:
name: nginx-required
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- key: region
operator: In
values:
- us-east-1
containers:
- name: nginx
image: nginx
注意:IgnoredDuringExecution 表示调度时强制执行,但 Pod 运行后若节点标签变化,不会驱逐 Pod。
2.2 软约束示例
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
- weight: 50
preference:
matchExpressions:
- key: region
operator: In
values:
- us-east-1
权重(weight)范围为 1-100,调度器会计算每个节点的匹配分数,选择总分最高的节点。
2.3 常用操作符
In:标签值在列表中。
NotIn:标签值不在列表中。
Exists:节点存在该标签(不关心值)。
DoesNotExist:节点不存在该标签。
Gt(大于)和 Lt(小于):仅适用于整数值。
三、Pod 亲和性与反亲和性
Pod 亲和性用于将某些 Pod 调度到同一节点或同一拓扑域(如可用区),反亲和性用于让 Pod 互相远离(如避免单点故障)。
3.1 Pod 亲和性示例(同一节点)
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
containers:
- name: webapp
image: nginx
该 Pod 将与带有标签 app=cache 的 Pod 调度到同一个节点(topologyKey=kubernetes.io/hostname 表示节点级别)。
3.2 Pod 反亲和性示例(分散到不同节点)
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
这确保 app=web 的 Pod 不会调度到已有相同标签 Pod 的节点上,常用于高可用部署(如多个副本分散到不同节点)。
3.3 topologyKey 的高级用法
kubernetes.io/hostname:节点级别。
topology.kubernetes.io/zone:可用区级别。
也可使用自定义标签(如 rack)。
四、污点(Taint)与容忍度(Toleration)
污点应用于节点,表示该节点“排斥”某些 Pod。容忍度应用于 Pod,表示 Pod 可以“容忍”节点上的污点。两者配合使用,可以实现:
专用节点(只允许特定 Pod 调度)。
特殊硬件节点(如 GPU 节点,只允许需要 GPU 的 Pod 调度)。
节点维护(使用 NoExecute 污点驱逐现有 Pod)。
4.1 添加污点
# 添加 NoSchedule 污点:不调度新 Pod,不影响现有 Pod
kubectl taint nodes node1 dedicated=gpu:NoSchedule
# 添加 NoExecute 污点:不仅不调度新 Pod,还会驱逐不匹配容忍度的现有 Pod
kubectl taint nodes node2 maintenance=true:NoExecute
# 添加 PreferNoSchedule:尽量不调度(软)
kubectl taint nodes node3 special=true:PreferNoSchedule
4.2 查看污点
kubectl describe node node1 | grep Taints
4.3 删除污点
kubectl taint nodes node1 dedicated:NoSchedule-
4.4 Pod 添加容忍度
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
tolerations:
- key: dedicated
operator: Equal
value: gpu
effect: NoSchedule
containers:
- name: gpu-app
image: nvidia/cuda:11.0-base
operator 可以是 Equal(值需匹配)或 Exists(仅检查 key 存在)。
effect 对应污点的 effect,如果不指定,表示容忍所有 effect。
4.5 常见场景:专用节点
标记节点:kubectl label node node1 node-role=monitoring
添加污点:kubectl taint nodes node1 dedicated=monitoring:NoSchedule
为监控 Pod 添加容忍度,且通过 nodeSelector 或亲和性确保调度到该节点。
五、节点维护操作:cordon / drain
cordon:将节点标记为不可调度(但已有 Pod 继续运行)。
drain:驱逐节点上的所有 Pod(优雅终止),并将其调度到其他节点,同时标记为不可调度。
# 封锁节点(新 Pod 不会调度到该节点)
kubectl cordon node1
# 驱逐节点上的所有 Pod(会优雅终止并重新调度)
kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
# 解封节点
kubectl uncordon node1
六、调度策略优先级总结
当多个调度约束同时存在时,调度器按以下顺序处理:
硬约束(required 亲和性、nodeSelector)必须满足。
软约束(preferred 亲和性)作为评分依据。
污点容忍度:Pod 必须容忍节点上所有的 NoSchedule 污点,否则不能调度。
资源请求(requests)也必须满足。
七、实战:将数据库调度到 SSD 节点,并保证副本分散
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- mysql
topologyKey: kubernetes.io/hostname
containers:
- name: mysql
image: mysql:8.0
必须调度到 disktype=ssd 节点。
同一节点上不会有两个 mysql Pod。
八、小结
调度策略是实现生产级部署的关键。nodeSelector 简单但功能有限;节点亲和性提供软硬约束;Pod 亲和性/反亲和性控制 Pod 间分布;污点和容忍度实现节点隔离。合理组合这些策略,可以满足绝大多数调度需求。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)