Skip to content

Kubernetes 调度

调度是把 Pod 放到合适 Node 上运行的过程。

默认情况下,kube-scheduler 会综合资源、约束、亲和性、污点、拓扑分布等因素选择节点。

常见调度控制手段:

  • nodeSelector
  • Node Affinity
  • Pod Affinity / Pod Anti-Affinity
  • Taints / Tolerations
  • Topology Spread Constraints

nodeSelector

最简单的节点选择方式。

给节点打标签:

shell
kubectl label node <node-name> disk=ssd

Pod 指定:

yaml
spec:
  nodeSelector:
    disk: ssd

只有带 disk=ssd 标签的节点才会被选择。

Node Affinity

Node Affinity 比 nodeSelector 表达能力更强。

硬约束:

yaml
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: disk
              operator: In
              values:
                - ssd

软约束:

yaml
affinity:
  nodeAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        preference:
          matchExpressions:
            - key: zone
              operator: In
              values:
                - zone-a

required 必须满足,preferred 尽量满足。

Pod Affinity

Pod Affinity 表示希望和某类 Pod 放在一起。

yaml
affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: backend
        topologyKey: kubernetes.io/hostname

这个例子表示:当前 Pod 必须调度到已经有 app=backend Pod 的同一个节点上。

Pod Anti-Affinity

Pod Anti-Affinity 表示希望和某类 Pod 分开。

yaml
affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: web
          topologyKey: kubernetes.io/hostname

这个例子表示:尽量不要把多个 app=web Pod 放到同一个节点。

Taints 与 Tolerations

Taint 是节点上的排斥标记,Toleration 是 Pod 对这个标记的容忍。

给节点加污点:

shell
kubectl taint node <node-name> dedicated=gpu:NoSchedule

Pod 容忍:

yaml
tolerations:
  - key: dedicated
    operator: Equal
    value: gpu
    effect: NoSchedule

Taint effect:

effect说明
NoSchedule不调度新的不容忍 Pod
PreferNoSchedule尽量不调度
NoExecute已运行的不容忍 Pod 也会被驱逐

删除污点:

shell
kubectl taint node <node-name> dedicated=gpu:NoSchedule-

Topology Spread Constraints

用于让 Pod 在节点、可用区等拓扑上均匀分布。

yaml
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: web

含义:带 app=web 的 Pod 在不同节点上的数量差距最多为 1。

nodeName

可以直接指定节点:

yaml
spec:
  nodeName: worker-1

这会绕过调度器,通常不推荐。除非是调试或特殊系统组件。

排查调度失败

Pod 一直 Pending 时:

shell
kubectl describe pod <pod-name>

Events 中常见原因:

  • CPU/Memory 不足。
  • PVC 未绑定。
  • nodeSelector 或 affinity 无匹配节点。
  • Taint 未被 toleration 容忍。
  • 拓扑分布约束无法满足。

查看节点:

shell
kubectl get node --show-labels
kubectl describe node <node-name>

参考