目录

Kubernetes 集群调度核心组件与协作机制

1. 关键组件及职责

2. List-Watch 工作机制(组件协作核心)

3. Pod 创建与调度全流程(基于 List-Watch)

(1)用户发起请求

(2)APIServer 处理与存储

(3)事件广播与组件响应

(4)Scheduler 调度流程(过滤→优选)

① 过滤阶段(Predicate:排除不满足条件的节点)

② 优选阶段(Priorities:对可行节点打分排序)

(5)绑定节点与 Pod 启动

4. 指定调度节点的 4 种方式

方式 1:nodeName(强制绑定节点,跳过 Scheduler)

方式 2:nodeSelector(基于节点标签匹配,强制约束)

方式 3:亲和性调度(节点亲和、Pod 亲和)

3.1 节点亲和性(NodeAffinity)

3.2 Pod 亲和性(PodAffinity)

方式 4:反亲和性调度(PodAntiAffinity)

5. 污点(Taint)与容忍(Toleration)

5.1 污点(Taint):节点的 “排斥标签”

5.2 容忍(Toleration):Pod 的 “例外许可”

6. 节点维护操作:cordon & drain

7. Pod 生命周期阶段(调度相关状态)

8. 调度故障排查核心命令

9. 调度策略优先级总结

核心思维总结


Kubernetes 集群调度核心组件与协作机制

Kubernetes 集群调度的核心是通过 List-Watch 机制 实现组件间解耦与实时数据同步,确保 Pod 高效、合规地调度到目标节点。

1. 关键组件及职责

组件 核心职责
kubectl / API 客户端 向 APIServer 发起资源创建 / 管理请求(如创建 Pod、Deployment),是用户操作入口。
APIServer 集群控制核心入口,负责权限校验、API 调用转发、与 etcd 交互存储集群状态。
etcd 分布式键值存储,保存集群所有资源(Pod、Node、配置等)的最终状态。
Controller Manager 维护集群状态一致性,如通过 ReplicaSet 确保 Pod 副本数、执行自愈(重建故障 Pod)。
Scheduler 调度器,为未绑定节点的 Pod 选择合适节点,核心逻辑是 “过滤 - 优选” 算法。
kubelet 节点代理,运行在每个 Node 上,负责 Pod 生命周期管理(拉取镜像、启动容器、状态上报)。

2. List-Watch 工作机制(组件协作核心)

List-Watch 是 Kubernetes 组件间同步状态的 “事件驱动模型”,流程如下:

  1. 启动监听:Controller Manager、Scheduler、kubelet 启动后,通过 HTTPS 持续监听 APIServer(6443 端口)的资源事件(如 Pod 创建、Node 状态变更)。
  2. 事件触发:当用户通过 kubectl apply 创建 Pod 时,APIServer 校验请求后将 Pod 信息写入 etcd,etcd 触发 Create 事件并同步给 APIServer。
  3. 组件响应:APIServer 将事件广播给监听的组件,各组件根据职责处理:
    • Controller Manager:监听副本控制器(如 Deployment),确保 Pod 副本数达标;
    • Scheduler:监听 “未绑定节点的 Pod”,执行调度逻辑分配节点;
    • kubelet:监听 “分配到本节点的 Pod”,启动容器并上报状态。

3. Pod 创建与调度全流程(基于 List-Watch)

(1)用户发起请求

用户通过 kubectl apply -f pod.yaml 向 APIServer 提交 Pod 创建请求。

(2)APIServer 处理与存储
  • APIServer 校验请求合法性(如权限、资源格式),通过后将 Pod 元数据写入 etcd。
  • etcd 确认写入后,返回 “创建成功” 给 APIServer,APIServer 再反馈给用户。
(3)事件广播与组件响应
  • etcd 触发 Pod Create 事件,同步给 APIServer;
  • APIServer 将事件广播给 Scheduler、Controller Manager、kubelet:
    • Controller Manager:若 Pod 由 Deployment 管理,检查副本数,确保符合 replicas 配置;
    • Scheduler:监听到 “未绑定节点的 Pod”(spec.nodeName == ""),启动调度流程。
(4)Scheduler 调度流程(过滤→优选)

Scheduler 核心任务是为 Pod 选择 “最优节点”,分两步执行:

① 过滤阶段(Predicate:排除不满足条件的节点)

通过预设算法筛选出 “能运行 Pod 的节点”,常见过滤规则:

过滤算法 功能描述
PodFitsResources 节点剩余 CPU / 内存是否满足 Pod 需求
PodFitsHost 若 Pod 指定 nodeName,匹配节点名
PodFitsHostPorts 节点端口是否被占用(避免端口冲突)
PodSelectorMatches 节点标签是否匹配 Pod 的 nodeSelector
NoDiskConflict 节点挂载的 Volume 是否与 Pod 需求冲突
  • 若无节点满足条件,Pod 会一直处于 Pending 状态,直到有节点符合条件。
② 优选阶段(Priorities:对可行节点打分排序)

对过滤后的节点按 “优先级权重” 排序,选择得分最高的节点,常见优选规则:

优选规则 描述
LeastRequestedPriority 节点资源(CPU / 内存)使用率越低,得分越高(均衡资源分配)。
BalancedResourceAllocation CPU 与内存使用率越接近,得分越高(避免单资源过载)。
ImageLocalityPriority 节点已缓存 Pod 所需镜像,得分越高(减少镜像拉取时间,提升启动速度)。
(5)绑定节点与 Pod 启动
  • Scheduler 将选中的节点信息写入 APIServer,APIServer 更新 etcd 中 Pod 的 spec.nodeName 字段;
  • 目标节点的 kubelet 监听到 “分配给自己的 Pod”,调用容器运行时(Docker/containerd):
    1. 拉取 Pod 所需镜像;
    2. 创建并启动容器;
    3. 将 Pod 状态(Running/Failed)上报给 APIServer;
  • APIServer 更新 etcd 中 Pod 的状态,集群状态同步完成,Pod 正式进入 Running 状态

4. 指定调度节点的 4 种方式

方式 1:nodeName(强制绑定节点,跳过 Scheduler)
  • 原理:直接在 Pod 模板中指定 spec.nodeName: 目标节点名,Pod 绕过 Scheduler,由目标节点的 kubelet 直接创建。
  • 特点:强制生效,不经过调度算法;若节点不存在或不可用,Pod 会一直 Pending。
  • 配置示例
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          nodeName: node1  # 强制调度到 node1
          containers:
          - name: myapp
            image: nginx:latest
    
  • 验证kubectl describe pod <pod-name> 无 Successfully assigned by default-scheduler 事件,直接由 kubelet 启动容器。
方式 2:nodeSelector(基于节点标签匹配,强制约束)
  • 原理:通过 Pod 的 spec.nodeSelector 匹配节点标签,Scheduler 仅调度到符合标签的节点。
  • 特点:强制约束,需先给节点打标签;若无匹配标签的节点,Pod 会 Pending。
  • 操作步骤
    1. 给节点打标签:kubectl label nodes node1 yjs=a(给 node1 打 yjs=a 标签);
    2. 配置 Pod 的 nodeSelector
      spec:
        nodeSelector:
          yjs: a  # 仅调度到有 `yjs=a` 标签的节点(如 node1)
      
  • 标签管理命令
    • 查看节点标签:kubectl get nodes --show-labels
    • 修改标签:kubectl label nodes node1 yjs=b --overwrite
    • 删除标签:kubectl label nodes node1 yjs-
方式 3:亲和性调度(节点亲和、Pod 亲和)

nodeSelector 仅支持 “精确标签匹配”,亲和性(Affinity)支持更灵活的调度规则,可基于 “节点标签” 或 “已运行 Pod 的标签”,且分为 硬策略(必须满足) 和 软策略(优先满足)

3.1 节点亲和性(NodeAffinity)
  • 原理:基于 节点标签 调度 Pod,支持复杂匹配逻辑(如 In/NotIn/Exists)。
  • 核心配置字段
    spec:
      affinity:
        nodeAffinity:
          # 硬策略:必须满足,否则 Pod Pending
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname  # 节点标签键(节点名)
                operator: NotIn  # 匹配方式:不在 values 列表中
                values:
                - node2  # 排除 node2,仅调度到其他节点
          # 软策略:优先满足,不满足也可调度到其他节点
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100  # 权重(0-100,数值越大优先级越高)
            preference:
              matchExpressions:
              - key: yjs  # 节点标签键
                operator: In
                values:
                - a  # 优先调度到 `yjs=a` 的节点(如 node1)
    
  • 操作符说明
    操作符 含义 示例
    In 标签值在列表中 key: yjs, operator: In, values: [a]
    NotIn 标签值不在列表中 key: hostname, operator: NotIn, values: [node2]
    Exists 节点存在该标签(无需值) key: env, operator: Exists
    DoesNotExist 节点不存在该标签 key: debug, operator: DoesNotExist
    Gt/Lt 标签值大于 / 小于指定数值 key: version, operator: Gt, values: [3]
3.2 Pod 亲和性(PodAffinity)
  • 原理:基于 已运行 Pod 的标签 调度新 Pod,让 “相关 Pod” 聚堆到同一拓扑域(如同一节点、同一可用区),减少网络延迟。
  • 核心配置字段(需指定 topologyKey 定义拓扑域范围):
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app  # 已运行 Pod 的标签键
                operator: In
                values:
                - db  # 匹配标签为 `app=db` 的 Pod
            topologyKey: kubernetes.io/hostname  # 拓扑域:同一节点(按节点名划分)
    
  • 场景示例:让 Web 服务 Pod(app=web)与数据库 Pod(app=db)调度到同一节点,减少跨节点网络开销。
方式 4:反亲和性调度(PodAntiAffinity)
  • 原理:与 Pod 亲和性相反,让新 Pod 避免 调度到 “已运行指定标签 Pod 的拓扑域”,实现 Pod 分散部署,提升高可用。
  • 核心配置字段
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app  # 已运行 Pod 的标签键
                operator: In
                values:
                - web  # 避免与 `app=web` 的 Pod 同节点
            topologyKey: kubernetes.io/hostname  # 拓扑域:同一节点
    
  • 场景示例:多个 Web 服务 Pod(app=web)分散到不同节点,避免单点故障(若一个节点宕机,其他节点的 Web Pod 仍可用)。

5. 污点(Taint)与容忍(Toleration)

亲和性是 “吸引 Pod 到节点”,污点是 “排斥 Pod 远离节点”,容忍则是 “让 Pod 可以忽略污点,调度到有污点的节点”。

5.1 污点(Taint):节点的 “排斥标签”
  • 作用:给节点添加污点后,不满足 “容忍” 条件的 Pod 无法调度到该节点;支持 3 种效果(effect):

    污点效果 作用
    NoSchedule 仅阻止新 Pod 调度到该节点,不影响已运行的 Pod(如节点维护时临时阻止新 Pod)。
    NoExecute 阻止新 Pod 调度,且驱逐节点上已运行但无容忍的 Pod(如节点故障时强制迁移 Pod)。
    PreferNoSchedule 软策略,尽量阻止新 Pod 调度,无其他节点时仍可调度(如非核心节点优先保留资源)。
  • 污点管理命令

    # 给 node1 添加污点:key1=value1:NoSchedule
    kubectl taint node node1 key1=value1:NoSchedule
    
    # 查看节点污点(Taints 字段)
    kubectl describe node node1 | grep Taints
    
    # 移除节点污点(末尾加 `-`)
    kubectl taint node node1 key1:NoSchedule-
    
5.2 容忍(Toleration):Pod 的 “例外许可”
  • 作用:给 Pod 添加容忍配置,让其可以忽略节点的指定污点,调度到该节点。
  • 核心配置字段(需与污点的 key/value/effect 匹配):
    spec:
      tolerations:
      - key: "key1"  # 匹配污点的 key
        operator: "Equal"  # 匹配方式:Equal(需 value 一致)或 Exists(忽略 value)
        value: "value1"  # 匹配污点的 value
        effect: "NoSchedule"  # 匹配污点的 effect
        tolerationSeconds: 3600  # 仅 NoExecute 生效:Pod 被驱逐前可保留的时间(秒)
    
  • 常见容忍场景
    1. 容忍所有污点:tolerations: - operator: "Exists"(不指定 key,忽略所有污点);
    2. 容忍指定 key 的所有效果:tolerations: - key: "key1", operator: "Exists"(忽略该 key 的所有 effect);
    3. Master 节点容忍:默认 Master 有 node-role.kubernetes.io/master:NoSchedule 污点,给 Pod 加容忍可调度到 Master(仅测试环境使用)。

6. 节点维护操作:cordon & drain

节点需要升级、检修时,需避免新 Pod 调度并安全迁移已运行 Pod,核心命令如下:

命令 作用
kubectl cordon <node> 标记节点为 “不可调度”(SchedulingDisabled),阻止新 Pod 调度,不影响已运行 Pod。
kubectl drain <node> --ignore-daemonsets --delete-local-data --force 驱逐节点上所有 Pod(忽略 DaemonSet Pod,删除本地数据),等价于 “cordon + 驱逐”。
kubectl uncordon <node> 取消 “不可调度” 标记,恢复节点可调度状态。
  • 场景示例:节点升级前执行 drain,确保 Pod 迁移到其他节点,避免业务中断。

7. Pod 生命周期阶段(调度相关状态)

Pod 调度过程中会经历不同生命周期阶段,核心状态与调度的关系如下:

阶段 含义 调度相关原因
Pending Pod 已创建,但未调度到节点,或正在拉取镜像。 1. 无满足条件的节点(如污点未容忍、资源不足);2. 镜像拉取缓慢。
Running Pod 已调度到节点,且所有容器正常运行。 调度成功,kubelet 启动容器完成。
Failed Pod 中所有容器终止,且至少一个容器异常退出(非 0 状态)。 容器启动失败(如镜像错误、命令错误),与调度无关。
Unknown 无法获取 Pod 状态(如 kubelet 与 APIServer 通信故障)。 节点网络异常,需排查节点连通性。

8. 调度故障排查核心命令

排查目标 命令 关键查看点
Pod 调度事件 kubectl describe pod <pod-name> Events 字段:是否有 FailedScheduling(调度失败原因,如污点未容忍、资源不足)。
节点污点与标签 kubectl describe node <node-name> Taints(污点)、Labels(标签):确认是否与 Pod 配置匹配。
节点资源使用情况 kubectl top node CPU / 内存使用率:是否因资源不足导致调度失败。
kubelet 运行日志 journalctl -xefu kubelet 节点级故障(如容器启动失败、镜像拉取错误)。
集群整体状态 kubectl get nodeskubectl cluster-info 节点是否 Ready、APIServer/etcd 是否正常运行。

9. 调度策略优先级总结

Kubernetes 调度按以下优先级筛选节点,优先级从高到低:

  1. nodeName:强制绑定节点,跳过 Scheduler;
  2. 污点与容忍:有污点的节点仅允许有对应容忍的 Pod 调度;
  3. 亲和性 / 反亲和性:硬策略优先满足,再满足软策略;
  4. nodeSelector:匹配节点标签;
  5. Scheduler 过滤 - 优选:默认调度算法(资源均衡、镜像本地化等)。

核心思维总结

调度的本质是 “让 Pod 按规则找到合适节点”,核心逻辑可概括为:“调度是吸引(亲和性),污点是排斥(Taint),容忍是例外(Toleration),硬策略必须满足,软策略灵活优先”

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐