K8s Lab 把当前仓库文档整理成一个可阅读的网页站点

Repository Reading Site

高级调度 — 控制 Pod 去哪里

**实验结果:** **原理:** 硬约束。不匹配的节点直接排除,无商量余地。 **required vs preferred:** | 类型 | 含义 | 不满足时 | |------|------|---------| | `required` | 硬约束,必须满足 | Pod 永远 Pending | | `preferred` | 软约束,尽量满足

Markdownphase-2/01-scheduling-advanced.md2026年4月9日 12:00

高级调度 — 控制 Pod 去哪里

调度器做决策的完整流程

Pod 创建 → Scheduler Watch 到
         → 过滤(哪些节点不行)
         → 打分(剩下的哪个最好)
         → 绑定(Pod → Node)
         → kubelet 拉起容器

四种调度控制手段

1. nodeSelector — 最简单的约束

spec:
  nodeSelector:
    topology.kubernetes.io/region: la    # 只去 LA 节点

实验结果:

  • la-only Pod → 调度到 us590068728056 (LA)
  • hk-only Pod → 调度到 wk-1 (HK)

原理: 硬约束。不匹配的节点直接排除,无商量余地。

2. nodeAffinity — 更灵活的节点选择

spec:
  affinity:
    nodeAffinity:
      # 硬约束:必须不是 Master
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: node-role.kubernetes.io/control-plane
            operator: DoesNotExist
      # 软约束:优先选 LA(但 HK 也行)
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: topology.kubernetes.io/region
            operator: In
            values: ["la"]

required vs preferred:

类型 含义 不满足时
required 硬约束,必须满足 Pod 永远 Pending
preferred 软约束,尽量满足 调度到其他节点

operator 支持: In, NotIn, Exists, DoesNotExist, Gt, Lt

3. TopologySpreadConstraints — 跨拓扑域均匀分布

spec:
  topologySpreadConstraints:
  - maxSkew: 1                              # 最大偏差
    topologyKey: topology.kubernetes.io/region  # 按什么维度分散
    whenUnsatisfiable: DoNotSchedule         # 不满足时:拒绝调度
    labelSelector:
      matchLabels:
        app: spread-demo

实验结果(6 副本,maxSkew=1,按 region 分散):

LA: 3 个 Pod(cp-3 × 1, us590068728056 × 2)
HK: 3 个 Pod(wk-1 × 3)
偏差: |3-3| = 0  1 

maxSkew 的含义: 任意两个拓扑域的 Pod 数量差不能超过 maxSkew。如果设为 2,则允许 LA:4 HK:2 这样的不均匀分布。

whenUnsatisfiable 两种策略:

  • DoNotSchedule — 不满足就不调度(硬约束)
  • ScheduleAnyway — 尽量满足但不强制(软约束)

面试深度题: "TopologySpreadConstraints 和 podAntiAffinity 的区别?"

  • podAntiAffinity: "我不要和同类 Pod 在同一个节点/zone"(二元:同/不同)
  • TopologySpread: "我要均匀分散,偏差不超过 N"(量化:允许多大偏差)

4. Taint/Toleration — "节点赶人"

Taint 是节点上的标记:"我有特殊情况,普通 Pod 别来"。 Toleration 是 Pod 上的声明:"我能容忍你的特殊情况"。

# 给节点加 Taint
kubectl taint nodes hk652699382121 region=hk:NoSchedule

# Pod 需要对应的 Toleration 才能调度上去
spec:
  tolerations:
  - key: "region"
    operator: "Equal"
    value: "hk"
    effect: "NoSchedule"

三种 effect:

Effect 含义
NoSchedule 新 Pod 不调度上来,已有 Pod 不影响
PreferNoSchedule 尽量不调度,但没其他选择时可以
NoExecute 新 Pod 不调度,已有 Pod 被驱逐

Master 为什么默认不跑业务 Pod? 因为 kubeadm 自动给 Master 加了 Taint:

node-role.kubernetes.io/control-plane:NoSchedule

模拟 GPU 调度

原理:Extended Resources

K8s 的 GPU 调度不是什么黑魔法——它使用 Extended Resources 机制:

  1. 设备插件(Device Plugin)向 kubelet 注册资源(如 nvidia.com/gpu: 2
  2. kubelet 上报给 API Server,写入 Node 的 status.capacity
  3. Pod 声明 resources.limits: nvidia.com/gpu: 1
  4. Scheduler 像分配 CPU/内存一样分配 GPU

实验:手动注册 fake GPU

# 通过 kubectl proxy + PATCH API 给节点注册 GPU
curl --request PATCH \
  --data '[{"op":"add","path":"/status/capacity/nvidia.com~1gpu","value":"2"}]' \
  http://localhost:8099/api/v1/nodes/wk-1/status

实验结果:

Pod 请求 GPU 调度到 原因
gpu-job-1 1 hk652699382121 有 1 GPU
gpu-job-2gpu 2 wk-1 唯一有 2 GPU 的节点
gpu-job-impossible 5 (Pending) 无节点有 5 GPU

面试重点:GPU 不能超配。 CPU 有 requests/limits 之分(limits 可以大于 requests,允许 burst),但 GPU 只有 limits,且 limits = requests,不允许超配。原因:GPU 不像 CPU 可以时间分片,一个进程占了 GPU 就独占了。

02-storage-nfs.md