# 实验前置:清理与打标签
## 清理之前的 Pod
kubectl delete pods -all
## 给 node1 打上磁盘类型标签 (SSD)
kubectl label nodes node1 disk=ssd
## 给 node2 打上磁盘区域标签 (Zone Top)
kubectl label nodes node2 zone=top
# 实验一:NodeSelector 与 NodeAffinity (定向调度)
目标:让 Pod 必须运行在 node1(SSD 节点),并优先选择 node2(但因为 node1 是硬性条件,最终会留在 node1)。
1、创建文件
affinity-test.yaml:
apiVersion: v1
kind: Pod
metadata:
name: affinity-pod
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
disk: ssd # 硬限制:只能去 node1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: zone
operator: In
values:
- top # 软限制:虽然想去 top(node2),但被上面的 ssd(node1) 拽住了
-
preferredDuringSchedulingIgnoredDuringExecution:调度时倾向于满足,但运行时如果环境变了则忽略”.简称:软亲和性 (Soft Affinity)。 -
weight: 1:权重。如果满足条件,给这个节点加 1 分。在复杂环境下,分数最高的节点胜出。 -
operator: In:匹配逻辑。表示节点的标签值必须在values列表(top)中。
2、验证
kubectl apply -f affinity-test.yaml
kubectl get pod affinity-pod -o wid
## 这里可以看见 Pod 运行在 node1 上
# 实验二:Taints & Tolerations(排他性调度)
目标:给 node2 加上污点,模拟需要额外付费或带 GPU 的特殊节点,普通 Pod 不准进来.
1、给 Node2 打上污点
kubectl taint nodes node2 hardware=gpu:NoSchedule
Kubernetes 的污点效果主要有三种,NoSchedule 是最常用的一种:
NoSchedule:“不准进来”。 如果一个 Pod 没有明确写明能够“容忍(Tolerate)”这个污点,那么新的 Pod 绝对不会被调度到这个节点上。但是,已经在节点上运行的 Pod 不受影响。
PreferNoSchedule:“尽量别进来”。 这是软性限制。调度器会尽量避免把 Pod 放到这个节点,但如果别的节点都满了,它还是会妥协。
NoExecute:“统统赶走”。 这是最狠的。不仅新 Pod 进不来,如果节点上现有的 Pod 没有对应的容忍度,会立刻被**驱逐(Evict)**出去。
验证污点有没有打上
kubectl describe node node2 grep Taints
2、创建一个没有任何容忍度的普通 Pod
kubectl run normal-pod --image=nginx
kubectl get pod normal-pod -o wide
这里会发现这个 Pod 不会去 node2,即使 node1 满了或者挂了,也会 Pending,
3、创建一个能容忍污点的 Pod
编辑 gpu-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
nodeSelector:
zone: top # 我们指定它去 node2
tolerations:
- key: "hardware"
operator: "Equal"
value: "gpu"
effect: "NoSchedule" # 只有声明了这一行的 Pod 才能进 node2
containers:
- name: nginx
image: nginx
4、验证
kubectl apply -f gpu-pod.yml
kubectl get pod gpu-pod -o wide
可以发现 gpu-pod 成功运行在node2 上了
# 实验三:驱逐实验
目标:当前街道突然变得不可用时,看看 Pod 会发生什么
1、观察当前:gpu-pod 在 node2 上运行
2、升级污点:将 NoSchedule 改为 NoExecute(立即驱逐不容忍的 Pod)
## 先删除旧污点,在打新污点
kubectl taint nodes node2 hardware:NoSchedule-
kubectl taint nodes node2 hardware=gpu:NoExecute
3、见证驱逐
可以提前在另一个终端窗口执行
kubectl get pods -w
会发现 gpu-pod 瞬间进入 Terminating 状态并消失了
这是因为 Tolerations 里写的是 NoSchedule,它不容忍 NoExecute。
# 实验后打扫
## 1. 删掉所有 Pod
kubectl delete pod --all
## 2. 移除节点标签
kubectl label nodes node1 disk-
kubectl label nodes node2 zone-
## 3. 移除节点污点
kubectl taint nodes node2 hardware:NoExecute-
## 4. 确认 Master 是否有污点(保持默认就好,除非你想让 Master 也跑 Pod)
kubectl describe node master grep Taints
# 总结
NodeSelector:是强制性的匹配。
NodeAffinity:更灵活,Required 是必须满足,Preferred 是尽量满足。
Taints (污点):是节点的属性,用来拒绝 Pod。
Tolerations (容忍度):是 Pod 的属性,用来克服污点。
NoSchedule vs NoExecute:前者只影响新 Pod 调度,后者会把已经在跑的旧 Pod 赶走。
命令
## 查看所有标签
kubectl get nodes --show-labels
## 查看特定标签(比如自定义的 disK 和 zone)
kubectl get nodes -L disk -L zone