Skip to content

Kubernetes 调度 ​

调度流程 ​

Scheduler 对未设置 spec.nodeName 的 Pending Pod 执行:

  1. 过滤:排除资源不足、端口冲突、卷拓扑不匹配、污点不可容忍、亲和性不满足的节点。
  2. 评分:依据资源、拓扑、亲和性、镜像局部性等插件给可行节点打分。
  3. 绑定:把选定节点写到 Pod。
  4. kubelet 再进行本地准入并启动 Pod;调度成功不保证镜像、挂载或容器启动成功。
bash
kubectl -n demo get pods --field-selector=status.phase=Pending
kubectl -n demo describe pod <pod>
kubectl -n demo events --for pod/<pod>

资源请求是调度依据 ​

Scheduler 依据 requests 与节点 Allocatable/已请求量做决策,不依据实时平均使用率:

bash
kubectl describe node worker-01
kubectl top node
kubectl top pod -A --sort-by=cpu

kubectl top 是当前指标,describe node 的 Allocated resources 是请求/限制汇总,二者回答不同问题。

nodeSelector 与 nodeName ​

yaml
spec:
  nodeSelector:
    node.kubernetes.io/instance-type: compute-optimized

nodeSelector 是简单等值约束。先由平台给节点打受控标签:

bash
kubectl label node worker-01 \
  example.com.node-restriction.kubernetes.io/workload-tier=trusted

生产隔离标签应把 node-restriction.kubernetes.io/ 放在 DNS 子域后的名称段中,并确认已启用 Node authorizer 和 NodeRestriction 准入插件,避免 kubelet 给自己添加高信任标签。

不要常规使用 spec.nodeName:它绕过 Scheduler,可能忽略资源、亲和性和部分污点检查,只适合特定系统场景。

节点亲和性 ​

yaml
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: topology.kubernetes.io/zone
              operator: In
              values: [zone-a, zone-b]
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 50
        preference:
          matchExpressions:
            - key: node.kubernetes.io/instance-type
              operator: In
              values: [compute-optimized]
  • required... 是硬约束,无法满足就 Pending。
  • preferred... 是软偏好,评分时加权。
  • IgnoredDuringExecution 表示节点标签后续变化通常不驱逐已运行 Pod。

硬约束越多,容量碎片和升级阻塞风险越大;高可用目标优先用软偏好与拓扑分布。

Pod 亲和与反亲和 ​

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

反亲和让同一应用尽量分散节点。硬反亲和在小集群、滚动升级或节点维护时容易让 Pod Pending;preferred 通常更有弹性。

Pod 亲和/反亲和在大集群计算成本更高,并依赖所有节点正确标注 topologyKey。

拓扑分布约束 ​

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

第一个约束要求跨可用区均衡,第二个尽量跨节点均衡。maxSkew 的计算与符合条件域、minDomains、节点亲和/污点策略有关;上线前用实际节点标签和缩容/故障场景验证。

污点与容忍 ​

bash
kubectl taint nodes worker-gpu-01 dedicated=gpu:NoSchedule

Pod 容忍:

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

Toleration 只是允许调度,不会保证去该节点;要与节点亲和/selector 配合。

Effect行为
NoSchedule新 Pod 不调度,已有 Pod 不受影响
PreferNoSchedule尽量避免调度
NoExecute新 Pod 不调度,不容忍的已有 Pod 被驱逐

NoExecute 可配 tolerationSeconds 延迟驱逐。移除污点:

bash
kubectl taint nodes worker-gpu-01 dedicated=gpu:NoSchedule-

PriorityClass 与抢占 ​

yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: business-critical
value: 100000
globalDefault: false
description: "经平台审批的关键业务优先级"
---
apiVersion: v1
kind: Pod
metadata:
  name: critical-worker
  namespace: demo
spec:
  priorityClassName: business-critical

高优先级 Pod 无合适节点时可能抢占低优先级 Pod,但抢占不是即时腾出容量,也不能解决硬亲和、PV 拓扑等问题。PriorityClass 是集群级资源,应由平台治理,避免所有团队都声明“最高优先级”。

preemptionPolicy: Never 可获得队列优先级而不抢占其他 Pod。

调度门控与自定义 Scheduler ​

Scheduling Gates 可让 Pod 在外部条件满足前保持未调度,控制器移除 Gate 后才进入调度。它比创建后反复阻止调度更高效,但 Gate 只能移除不能追加,使用者要负责卡住对象的监控。

自定义 Scheduler 或调度插件会改变全局放置语义,应先证明内置插件无法满足,并建立兼容性、性能和故障回退测试。

Pending 排障 ​

常见 FailedScheduling 原因:

Event 片段排查方向
Insufficient cpu/memoryrequests、节点 Allocatable、容量扩展
untolerated taint节点污点与 Pod toleration
didn't match node affinity/selector标签和值、硬约束
pod anti-affinity rules选择器、拓扑域、可用节点数
unbound immediate PVCPVC/StorageClass/制备器
volume node affinity conflictPV 可用区与节点拓扑
max node group size reached节点扩容器与云配额
bash
kubectl -n demo get pod <pod> -o yaml
kubectl get nodes --show-labels
kubectl describe node <node>
kubectl -n demo get pvc

不要通过不断删除 Pending Pod解决调度约束;控制器会创建同样的 Pod。修正资源、容量或规则源头。

生产调度原则 ​

  • 每个容器都有基于观测数据设置的 requests。
  • 关键服务跨节点/区域分布,但硬约束不超过真实容量。
  • 专用节点同时使用 taint 和受保护 label/affinity。
  • 系统守护进程、关键业务、批处理使用治理过的优先级层次。
  • 滚动升级所需 Surge 容量、PDB 和节点维护余量纳入容量模型。
  • Pending、调度延迟、不可调度原因和抢占有告警。

继续阅读