---
url: /courses/kubernetes-cluster/11-pod-scheduling/index.md
---
# 第十一节 Pod 调度策略与位置约束

::: tip 本课目标
为虚构业务“云帆商城”设计可解释的 Pod 放置规则；比较 nodeName、nodeSelector、节点亲和性、Pod 反亲和性以及污点与容忍，并诊断因约束冲突产生的 Pending。
:::

## 11.1 接单：让调度器做有依据的选择

默认调度不是随机分配。调度器先过滤不满足资源与硬约束的节点，再对候选节点评分，最后完成绑定。

调度策略要回答三个问题：

1. 哪些节点绝对不能运行该 Pod？
2. 哪些节点更合适，但不满足时仍可运行？
3. 多个副本是否需要分散，避免单节点故障同时影响全部实例？

## 11.2 为节点建立可验证的业务标签

课程集群使用 `yunfan-worker` 和 `yunfan-worker2`。先查看实际节点，再添加自定义前缀标签：

```bash
kubectl get nodes
kubectl label node yunfan-worker \
  yunfan.example/workload=general \
  yunfan.example/zone=a \
  --overwrite
kubectl label node yunfan-worker2 \
  yunfan.example/workload=storage \
  yunfan.example/zone=b \
  --overwrite
kubectl get nodes -L yunfan.example/workload,yunfan.example/zone
```

若采用第 2 课低配集群，只有一个工作节点，应保留语法练习，并把“跨节点分散”记录为环境受限项。

## 11.3 从直接绑定到声明式选择

`nodeName` 直接指定节点并绕过调度器，适合诊断和极少数系统场景，不适合作为日常策略。**nodeSelector** 是最简单的硬约束；节点亲和性则能表达集合条件与软偏好。

```bash
kubectl apply -f manifests/11-scheduling/scheduling-baseline.yaml
kubectl get pod -n yunfan-shop -o wide
kubectl describe pod yunfan-storage-check -n yunfan-shop
```

软反亲和性表达“尽量分散”，资源不足时仍允许同节点；若改成硬约束，单工作节点环境会让第二个副本 Pending。

## 11.4 污点与容忍：节点拒绝谁

亲和性从 Pod 角度选择节点；污点从节点角度排斥 Pod。**tolerations** 只表示 Pod 可以容忍污点，不会主动把 Pod 吸引到该节点，因此通常还要配合 nodeSelector 或节点亲和性。

```bash
kubectl apply -f manifests/11-scheduling/toleration.yaml
kubectl get pod yunfan-database-slot -n yunfan-shop -o wide
```

`NoSchedule` 不会驱逐已经运行的 Pod；`NoExecute` 还会影响现有 Pod，且可能触发驱逐。本课只使用 NoSchedule，避免扩大影响。

## 11.5 故障演练：互相冲突的硬约束

复制 `yunfan-storage-check`，把资源名改为 `yunfan-impossible`，并增加一个不存在的标签：

```yaml
nodeSelector:
  yunfan.example/workload: storage
  yunfan.example/gpu: required
```

应用后诊断：

```bash
kubectl get pod yunfan-impossible -n yunfan-shop
kubectl describe pod yunfan-impossible -n yunfan-shop
kubectl get nodes --show-labels
kubectl get events -n yunfan-shop \
  --sort-by=.metadata.creationTimestamp
```

Pending 本身不是根因；`FailedScheduling` 事件会说明没有节点同时满足标签、污点、资源等条件。修复前先确认业务真正需要的是硬约束还是软偏好。

## 11.6 策略选择表

| 需求 | 推荐机制 | 关键边界 |
| --- | --- | --- |
| 临时诊断时精确指定节点 | nodeName | 绕过调度器 |
| 必须运行在一类节点 | nodeSelector / required nodeAffinity | 条件不满足会 Pending |
| 尽量运行在更合适的节点 | preferred nodeAffinity | 不是保证 |
| 副本尽量分散 | podAntiAffinity 或 topology spread | 需选择稳定 topologyKey |
| 专用节点拒绝普通 Pod | taint + toleration | 容忍不等于选择 |

## 11.7 清理与交付

```bash
kubectl delete -f manifests/11-scheduling/scheduling-baseline.yaml
kubectl delete -f manifests/11-scheduling/toleration.yaml
kubectl delete pod yunfan-impossible -n yunfan-shop --ignore-not-found
kubectl taint node yunfan-worker2 dedicated=database:NoSchedule-
```

交付内容：

1. 节点标签表和三类调度清单。
2. Pod 实际节点位置截图。
3. `FailedScheduling` 事件与修复说明。
4. 一份硬约束、软偏好、污点与容忍的选择理由。

{{reflection-checkpoint:pod-scheduling-check}}

## 本章小测

{{assessment:pod-scheduling}}

## 本章小结

* 调度器通过过滤、评分和绑定选择节点。
* nodeSelector 与 required affinity 是硬约束，preferred affinity 是软偏好。
* Pod 反亲和性可分散副本，污点可保护专用节点。
* toleration 只允许进入，通常还需配合节点选择规则。
* Pending 排错应以 FailedScheduling 事件为核心证据。
