一、 Pod 调度策略深度解析
Kubernetes 的默认调度器(default-scheduler)通过三个核心步骤将 Pod 分配到节点上:
-
预选(Predicates):排除不满足基本条件的节点(如内存不足、端口冲突)。
-
优选(Priorities):在剩余节点中,根据权重进行打分(如选择资源利用率低的节点)。
-
绑定:将 Pod 绑定到得分最高的节点。
除了默认的调度逻辑,我们可以通过以下策略控制 Pod 的去向:
1. 节点标签与调度
-
指定节点名称调度(硬指定)
-
特点:绕过调度器,强制 Pod 运行在特定节点。
-
场景:测试环境或特殊硬件需求的节点。
-
配置 :在
spec.nodeName中指定节点名。
-
-
指定节点标签调度(软指定)
-
特点:通过节点标签(Labels)进行匹配,需经过调度器。
-
逻辑步骤:
-
给节点打标签:
kubectl label nodes <node-name> <key>=<value> -
编辑 Pod YAML,使用
nodeSelector指定标签。
-
-
2. 亲和性策略(Affinity)
亲和性用于表达"偏好"或"强制要求",分为节点亲和性(Node Affinity) 和Pod 亲和性(Pod Affinity)。
-
节点亲和性 (
nodeAffinity)-
作用:让 Pod 倾向于运行在带有特定标签的节点上。
-
策略类型:
-
requiredDuringSchedulingIgnoredDuringExecution:硬策略,必须满足,否则 Pod 处于 Pending 状态。 -
preferredDuringSchedulingIgnoredDuringExecution:软策略,尽量满足,不满足也能运行。
-
-
匹配逻辑(操作符):
-
In,NotIn:包含/不包含(最常用)。 -
Exists,DoesNotExist:存在/不存在(只需判断键,无需值)。 -
Gt,Lt:大于/小于(针对整数值)。
-
-
-
Pod 亲和性 (
podAffinity)-
作用:让 Pod 倾向于与其他 Pod 运行在同一拓扑域(如同一节点、同一可用区)。
-
场景:微服务间的低延迟通信(如前端与后端同节点)。
-
反亲和性 (
podAntiAffinity) :让 Pod 尽量不与其他 Pod 运行在同一拓扑域。 -
核心配置:
-
labelSelector:选择哪些 Pod 的标签作为参照。 -
topologyKey:定义"拓扑域"的键(通常使用kubernetes.io/hostname表示节点级别,或使用云平台标签表示可用区级别)。
-
-
3. 实战示例
-
示例 1:节点亲和性(软策略)
yaml
yaml
affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: env operator: In values: [ "production" ]- 解释 :尽量将 Pod 调度到
env=production的节点,如果没有,也可以运行在其他节点。
- 解释 :尽量将 Pod 调度到
-
示例 2:Pod 反亲和性(硬策略)
yaml
yaml
affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: [ "myapp" ] topologyKey: kubernetes.io/hostname- 解释 :强制要求同一个节点上不能运行两个
app=myapp的 Pod(实现高可用,避免单点故障)。
- 解释 :强制要求同一个节点上不能运行两个
二、 污点与容忍度(Taints & Tolerations)
污点是节点的属性,用于排斥 Pod;容忍度是 Pod 的属性,用于允许被调度到有污点的节点。
1. 污点的作用
-
NoSchedule:不将 Pod 调度到带有该污点的节点(除非 Pod 有容忍度)。
-
PreferNoSchedule:尽量避免调度,但不是强制。
-
NoExecute:不调度新 Pod,并驱逐节点上已有的 Pod(除非 Pod 有容忍度)。
2. 设置污点
bash
bash
kubectl taint node <node-name> <key>=<value>:<effect>
-
示例:
bash
bash
kubectl taint node k8s-node01 key1=value1:NoSchedule
3. 容忍度(Tolerations)
在 Pod 的 YAML 中添加 tolerations字段,允许 Pod 被调度到有特定污点的节点。
-
配置示例:
yaml
yaml
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" -
解释 :该 Pod 可以容忍
key1=value1:NoSchedule的污点,因此可以被调度到k8s-node01。
4. 典型应用场景
-
专用节点 :给 GPU 节点打上
dedicated=gpu:NoSchedule污点,只有带有容忍度的 Pod(如 AI 训练任务)才能运行。 -
维护模式 :给节点打上
maintenance=true:NoExecute污点,驱逐所有非必要 Pod,进行维护。 -
弹性伸缩:在云平台上,通过污点标记节点即将被销毁,让 Pod 自动迁移。
三、 综合实战场景
场景:我们有一个 Redis 集群,希望:
-
Redis Pod 尽量运行在可用区 A(杭州)。
-
Redis Pod 之间不能运行在同一节点(避免单点故障)。
-
只有带有
redis-role=master标签的节点才能运行 Redis Pod。
YAML 配置:
yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
affinity:
# 1. 节点亲和性:尽量运行在可用区A(假设可用区A的标签是 zone=hangzhou)
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: zone
operator: In
values: [ "hangzhou" ]
# 2. Pod反亲和性:不能运行在同一节点
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [ "redis" ]
topologyKey: kubernetes.io/hostname
# 3. 节点亲和性(硬策略):必须运行在带有 redis-role=master 标签的节点
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- matchExpressions:
- key: redis-role
operator: In
values: [ "master" ]
四、 总结
| 概念 | 作用 | 方向 | 示例 |
|---|---|---|---|
| 节点亲和性 | Pod 倾向于运行在特定标签的节点 | Pod → Node | env=production |
| Pod 亲和性 | Pod 倾向于与其他 Pod 同拓扑域 | Pod → Pod | 同节点、同可用区 |
| Pod 反亲和性 | Pod 倾向于不与其他 Pod 同拓扑域 | Pod → Pod | 不同节点、不同可用区 |
| **污点 (Taint)** | 节点排斥 Pod | Node → Pod | dedicated=gpu:NoSchedule |
| **容忍度 (Toleration)** | Pod 允许被调度到有污点的节点 | Pod → Node | 容忍 dedicated=gpu:NoSchedule |
通过合理组合亲和性和污点,可以实现复杂的调度策略,满足生产环境的高可用、资源隔离、成本优化等需求。