01 - K8s 调度机制
调度器工作原理
Scheduler 决定 Pod 运行在哪个节点,过程分为两步:
新 Pod 创建
│
▼
┌─────────────────┐
│ 过滤 (Filter) │ 排除不满足条件的节点
│ - 资源是否足够 │
│ - 标签是否匹配 │
│ - 污点容忍 │
└────────┬────────┘
│ 候选节点列表
▼
┌─────────────────┐
│ 打分 (Score) │ 给候选节点排序
│ - 资源均衡 │
│ - 亲和性权重 │
│ - 自定义优先级 │
└────────┬────────┘
│ 最高分节点
▼
绑定 Pod 到节点nodeSelector(最简单的调度约束)
bash
# 给节点打标签
kubectl label nodes node-1 disktype=ssd
kubectl label nodes node-2 disktype=hddyaml
spec:
nodeSelector:
disktype: ssd # Pod 只会调度到有此标签的节点
containers:
- name: app
image: myappNode Affinity(节点亲和性)
比 nodeSelector 更灵活,支持"软性"偏好:
yaml
spec:
affinity:
nodeAffinity:
# 硬性要求(必须满足)
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values: ["linux"]
# 软性偏好(尽量满足,不满足也能调度)
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: disktype
operator: In
values: ["ssd"]操作符
| 操作符 | 含义 |
|---|---|
In | 值在列表中 |
NotIn | 值不在列表中 |
Exists | 键存在 |
DoesNotExist | 键不存在 |
Gt | 大于(仅限数字) |
Lt | 小于(仅限数字) |
Pod Affinity / Anti-Affinity(Pod 亲和/反亲和)
控制 Pod 之间的调度关系。
yaml
spec:
affinity:
# Pod 亲和:和某些 Pod 调度到同一区域
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: cache
topologyKey: kubernetes.io/hostname
# Pod 反亲和:和某些 Pod 不在同一个节点
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: web
topologyKey: kubernetes.io/hostname使用场景:
- 亲和:把 Web 和 Cache 调度到同一节点(减少网络延迟)
- 反亲和:同一 Deployment 的 Pod 分散到不同节点(高可用)
Taints 和 Tolerations(污点与容忍)
Taint(污点)标记在节点上,阻止 Pod 调度过来。 Toleration(容忍)声明在 Pod 上,表示可以容忍某些污点。
bash
# 给节点添加污点
kubectl taint nodes node-1 gpu=true:NoSchedule
# 移除污点
kubectl taint nodes node-1 gpu=true:NoSchedule-yaml
# Pod 声明容忍
spec:
tolerations:
- key: "gpu"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: training
image: pytorchTaint Effect(效果)
| 效果 | 说明 |
|---|---|
NoSchedule | 不容忍的 Pod 不会被调度到此节点 |
PreferNoSchedule | 尽量不调度(软性) |
NoExecute | 不容忍的 Pod 会被驱逐,新的不会调度 |
典型场景:
- GPU 节点只跑训练任务
- Master 节点不跑业务 Pod
- 维护节点驱逐所有 Pod
实操练习
bash
# 查看节点标签
kubectl get nodes --show-labels
# 查看节点的污点
kubectl describe node <node-name> | grep Taints
# Docker Desktop 的单节点上实验
kubectl label node docker-desktop env=dev
kubectl get nodes -l env=dev