Pod 调度与亲和性

新创建的 Pod 该放到哪台节点?默认交给 kube-scheduler 自动决定,但很多场景需要人工干预:应用要跑在有 GPU 的机器、副本要分散到不同节点、维护节点时要把 Pod 迁走。调度器提供节点选择、亲和性、污点容忍等机制来满足这些诉求。

kube-scheduler 的调度流程

kube-scheduler 调度流程 调度器对每个待调度 Pod 分两步决策:

  1. 过滤(Filtering):先筛掉不满足硬性条件的节点,如资源不足、端口冲突、不匹配的污点。
  2. 打分(Scoring):对剩余节点打分,选择总分最高的节点放置 Pod。

Pod 一直 Pending 时,多数是因为过滤阶段没有节点可用,用 describe 看事件即可确认原因:

kubectl describe pod xxx | tail -20
# 输出:Events:  FailedScheduling  0/3 nodes are available ...

nodeSelector 与 nodeName

nodeSelector 按节点标签选择节点,先给节点打标签再引用:

kubectl label node node01 disktype=ssd
kubectl get nodes --show-labels | grep ssd
spec:
  nodeSelector:
    disktype: ssd          # 只调度到带此标签的节点

nodeName 直接把 Pod 钉到指定节点(跳过调度器),一般仅用于调试。

节点亲和性 nodeAffinity

比 nodeSelector 更强:required 是硬性要求(无匹配节点则 Pending),preferred 是软偏好(尽量满足,不满足也能调度到别处):

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: disktype
                operator: In
                values: ["ssd"]
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          preference:
            matchExpressions:
              - key: zone
                operator: In
                values: ["zone-a"]

运算符还有 NotIn、Exists、DoesNotExist 等。podAffinity/podAntiAffinity 则按「与其他 Pod 的关系」调度,如让副本分散在不同节点。

污点 Taints 与容忍 Tolerations

污点打在节点上,标记「我不欢迎这类 Pod」;容忍加在 Pod 上,表示「我可以忍受这个污点」。二者配合实现「某些节点只跑特定负载」:

kubectl taint nodes node01 gpu=true:NoSchedule
# 输出:node/node01 tainted
kubectl taint nodes node01 gpu=true:NoSchedule-    # 减号移除污点
spec:
  tolerations:
    - key: gpu
      operator: Equal
      value: "true"
      effect: NoSchedule

effect 类型:NoSchedule 拒绝新调度、PreferNoSchedule 尽量不调度、NoExecute 立即驱逐不匹配的既有 Pod。

节点维护:cordon 与 drain

下线节点前先禁止新 Pod 调度,再优雅清空上面的 Pod:

kubectl cordon node01                 # 标记不可调度
kubectl drain node01 --ignore-daemonsets --delete-emptydir-data   # 驱逐 Pod
kubectl uncordon node01               # 恢复可调度

drain 会先让 Pod 优雅终止再迁移到其他节点,完成后节点才可安全维护。

小结:调度器先过滤再打分;nodeSelector/节点亲和性决定 Pod 去哪些节点,污点+容忍实现「指定节点只跑指定负载」;维护节点用 cordon 挡新调度、drain 清空 Pod、uncordon 恢复。

笔记加载中…