Scheduler

Kubernetes Scheduler 代码结构 #

仓库地址: github.com/kubernetes/kubernetes


整体代码布局 #

kubernetes/
├── cmd/kube-scheduler/          # 入口:二进制启动命令
│   ├── scheduler.go             # main() 入口
│   └── app/                     # cobra 命令、选项解析、初始化
│
└── pkg/scheduler/               # 核心实现
    ├── scheduler.go             # Scheduler 主结构体 + Run()
    ├── schedule_one.go          # 单 Pod 调度完整流程
    ├── schedule_one_podgroup.go # PodGroup(批量调度)
    ├── eventhandlers.go         # Informer 事件处理
    ├── extender.go              # 外部扩展调度器
    │
    ├── framework/               # 调度框架(插件系统)
    │   ├── interface.go         # 所有扩展点接口定义
    │   ├── types.go             # 核心类型(NodeInfo、CycleState 等)
    │   ├── cycle_state.go       # 调度周期状态传递
    │   ├── runtime/             # 框架运行时(插件注册/调用)
    │   ├── plugins/             # 内置插件实现
    │   └── preemption/          # 抢占逻辑
    │
    ├── apis/config/             # KubeSchedulerConfiguration API
    ├── profile/                 # 多调度 Profile 支持
    ├── metrics/                 # Prometheus 指标
    ├── backend/                 # 调度队列后端
    ├── util/                    # 工具函数
    └── testing/                 # 测试工具

核心文件解析 #

1. scheduler.go — 主结构体与启动 #

type Scheduler struct {
    Cache           internalcache.Cache       // 节点/Pod 缓存
    Extenders       []fwk.Extender            // 外部调度扩展
    NextEntity      func() (QueuedEntityInfo, error)  // 从队列取 Pod
    SchedulePod     func() (ScheduleResult, error)    // 核心调度函数
    FailureHandler  FailureHandlerFn                   // 失败处理
    SchedulingQueue internalqueue.SchedulingQueue      // 调度队列
    Profiles        profile.Map                        // 多 Profile
    StopEverything  <-chan struct{}                    // 停止信号
}

func (sched *Scheduler) Run(ctx context.Context) {
    sched.SchedulingQueue.Run(logger)  // 启动调度队列
    go wait.UntilWithContext(ctx, sched.scheduleOne, 0)  // 无限循环调度
}

核心逻辑Run() 启动后不断调用 scheduleOne() 从队列取 Pod 并调度。


2. schedule_one.go — 单 Pod 调度完整生命周期 #

这是调度器最核心的文件,实现了完整的调度周期(Scheduling Cycle):

func (sched *Scheduler) scheduleOnePod(ctx context.Context, podInfo *framework.QueuedPodInfo) {
    // 1. 获取对应的调度 Profile/Framework
    fwk := sched.Profiles[pod.Spec.SchedulerName]

    // 2. 创建 CycleState(用于在插件间传递数据)
    state := framework.NewCycleState()

    // 3. 执行调度算法(findNodesThatFitPod + scoreNodes)
    scheduleResult, err := sched.SchedulePod(ctx, fwk, state, podInfo)

    // 4. 执行绑定周期(Reserve → PreBind → Bind → PostBind)
    go sched.bindingCycle(ctx, state, fwk, ...)
}

调度框架(Scheduling Framework) #

调度框架是一个插件化的扩展点系统,定义在 interface.go

扩展点(Extension Points) #

┌─────────────────────────────────────────────────────────────────────┐
│                        Scheduling Cycle(调度周期)                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  QueueSort ──→ PreFilter ──→ Filter ──→ PostFilter ──→ Score       │
│       │            │            │            │            │         │
│       │            │            │            │            │         │
│       │            ▼            ▼            ▼            ▼         │
│       │      [PreFilter    [Filter     [PostFilter   [Score        │
│       │       Result]      NodeA/B/C]   (抢占)]      Nodes]        │
│       │                                                             │
│       └──────────────────────────────┐                             │
│                                      ▼                             │
│                              Reserve ──→ Permit ──→ PreBind        │
│                                  │          │           │          │
├──────────────────────────────────┼──────────┼───────────┼──────────┤
│                           Binding Cycle(绑定周期)                  │
│                                  │          │           │          │
│                                  ▼          ▼           ▼          │
│                               [Bind] ──→ PostBind                  │
└─────────────────────────────────────────────────────────────────────┘

各扩展点说明 #

扩展点阶段作用
QueueSort入队决定 Pod 在调度队列中的优先级
PreFilter调度前预处理/过滤(如检查 PVC 是否可用)
Filter过滤谓词计算,排除不满足条件的节点
PostFilter过滤后无可用节点时触发抢占(Preemption)
Score打分对可行节点打分排序
Reserve预留预留资源(如 Volume、端口)
Permit准入延迟绑定(如等待 Gang 调度)
PreBind绑定前执行绑定前准备(如挂载 Volume)
Bind绑定实际将 Pod 绑定到 Node
PostBind绑定后清理、通知

内置插件(framework/plugins/#

plugins/
├── defaultbinder/        # 默认绑定器
├── defaultpreemption/    # 默认抢占
├── interpodaffinity/     # Pod 间亲和/反亲和
├── nodeaffinity/         # 节点亲和性
├── nodeports/            # 检查节点端口冲突
├── noderesources/        # 资源(CPU/内存)检查
├── nodeunschedulable/    # 节点可调度性检查
├── nodevolumelimit/      # 节点 Volume 限制
├── podtopologyspread/    # Pod 拓扑分散约束
├── prioritysort/         # 优先级排序
├── volumebinding/        # Volume 绑定
├── volumerestrictions/   # Volume 限制
├── volumzone/            # Volume 可用区
└── ...(约 20+ 个内置插件)

关键数据流 #

                    ┌──────────────────────┐
                    │  未调度 Pod(Pending) │
                    └──────────┬───────────┘
                               ▼
                    ┌──────────────────────┐
                    │   Scheduling Queue   │ ← QueueSort 插件排序
                    │  (PriorityQueue)     │
                    └──────────┬───────────┘
                               ▼
                    ┌──────────────────────┐
                    │  scheduleOne()       │
                    │  ├─ PreFilter        │
                    │  ├─ Filter(谓词)   │ ← 并行检查所有节点
                    │  ├─ Score(打分)    │ ← 并行打分
                    │  └─ Reserve          │
                    └──────────┬───────────┘
                               ▼
                    ┌──────────────────────┐
                    │  bindingCycle()      │
                    │  ├─ PreBind          │
                    │  ├─ Bind             │
                    │  └─ PostBind         │
                    └──────────┬───────────┘
                               ▼
                    ┌──────────────────────┐
                    │  Pod 已绑定到 Node   │
                    └──────────────────────┘

核心数据结构 #

// 调度结果
type ScheduleResult struct {
    SuggestedHost string  // 选中的节点名
}

// 节点信息快照
type NodeInfo struct {
    Node         *v1.Node
    Pods         []*PodInfo
    UsedPorts    HostPortInfo
    Allocated    *Resource
    ...
}

// 调度周期状态(插件间传递)
type CycleState struct {
    states map[StateKey]StateData  // 插件可读写
}

配置入口 #

Scheduler 通过 KubeSchedulerConfiguration 配置:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
  plugins:
    filter:
      enabled:
      - name: NodeResourcesFit
    score:
      enabled:
      - name: NodeResourcesFit
        weight: 1

总结 #

模块核心文件职责
入口cmd/kube-scheduler/启动、配置解析
主循环scheduler.go + schedule_one.go调度主流程
框架framework/插件注册、调用、状态传递
插件framework/plugins/内置调度策略实现
队列backend/优先级队列管理
抢占framework/preemption/Pod 抢占逻辑

Reference #