Kubernetes 默认调度器适合处理无差别工作负载,但在实时业务与批处理任务混部的环境中,调度决策会直接决定请求延迟、排队时间和服务可用性。实时业务通常要求毫秒级响应和稳定的资源供给,而默认调度器主要根据资源请求、节点亲和和空闲率打分,并不会自动感知业务优先级。要实现实时业务优先调度,需要从优先级类、抢占策略、QoS 等级、自定义调度插件和节点拓扑五个层面共同设计。以下内容将围绕这些机制展开,并给出可落地的配置与代码示例。

一、PriorityClass 与抢占机制如何配合
PriorityClass 是 Kubernetes 提供的非命名空间对象,用于给 Pod 分配一个整数值优先级。数值越大,调度器越优先处理。除了优先级,PriorityClass 还包含 preemptionPolicy 字段,决定该优先级 Pod 是否可以抢占低优先级 Pod。当集群资源不足时,高优先级 Pod 会进入 Pending,调度器会尝试驱逐部分低优先级 Pod,为前者腾出空间。这个抢占动作对实时业务尤其重要,因为它避免了关键服务长时间等待资源释放。
配置 PriorityClass 时,建议为实时业务设置较高 value,例如 100000,为离线任务设置 10,为默认工作负载保留 0。注意不要把所有业务都设置成高优先级,否则集群会频繁发生抢占,反而增加不稳定。抢占牺牲者选择会优先考虑低优先级、BestEffort QoS 或资源使用较少的 Pod。可以通过 preemptionPolicy: Never 禁止某些 PriorityClass 触发抢占,但对于实时关键业务,保持默认的 PreemptLowerPriority 更合适。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: realtime-high
value: 100000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: 实时业务高优先级
---
apiVersion: v1
kind: Pod
metadata:
name: realtime-gateway
labels:
app: realtime-gateway
spec:
priorityClassName: realtime-high
containers:
- name: gateway
image: nginx:1.25
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "2"
memory: "4Gi"
需要说明的是,抢占不等同于普通驱逐。调度器在选择牺牲者后会向 API Server 提交删除请求,被抢占的 Pod 会按照终止宽限期退出。高优先级 Pod 要获得抢占收益,还需要节点有足够的可分配资源,并且调度器启用了 DefaultPreemption 插件。在大型集群中,建议监控抢占次数和 Pending 时长,避免因优先级设置过高造成其他业务频繁被打断。
二、QoS 等级与资源预留对实时业务的作用
实时业务除了调度优先级,还需要稳定的运行保障。Kubernetes 通过 QoS 等级决定 Pod 在资源紧张时的驱逐顺序。Guaranteed、Burstable、BestEffort 三个等级中,Guaranteed 的 Pod 最不容易被优先驱逐。要获得 Guaranteed,Pod 中每个容器都必须为 CPU 和内存同时设置 requests 与 limits,并且两者相等。对于视频流转码、交易网关、在线推理等实时场景,建议将核心容器配置为 Guaranteed,避免节点内存压力时被 kubelet 快速回收。
显式声明 requests 还能帮助调度器准确计算节点可分配资源。如果只设置 limits,Kubernetes 会把 requests 默认设为与 limits 相同,这在某些版本中是支持的,但显式声明可以避免理解偏差。同时,节点层面的资源预留要合理:kubelet 会为系统组件、内核和驱逐阈值保留资源,调度器看到的可分配资源小于节点总容量。如果实时 Pod 的 requests 过大,可能无法调度;如果 requests 过小,节点超卖后又会造成 CPU 争抢。因此实时业务需要经过压测确定真实资源需求,而不是简单复制离线任务配置。
apiVersion: v1
kind: Pod
metadata:
name: realtime-inference
spec:
priorityClassName: realtime-high
containers:
- name: inference
image: my-inference:latest
resources:
requests:
cpu: "4"
memory: "8Gi"
limits:
cpu: "4"
memory: "8Gi"
这里 CPU 和内存的 requests 与 limits 完全一致,因此该 Pod 会被标记为 Guaranteed。QoS 等级与 PriorityClass 不同:QoS 影响节点压力和驱逐,PriorityClass 影响调度排序和抢占。两者组合起来,实时业务既能在调度阶段抢到资源,也能在运行阶段获得更高生存概率。配置时不要只依赖 QoS 而忽略优先级,也不要只设置高优先级而不声明资源,这两类信息在调度链路上是互补关系。
三、调度框架与自定义插件实现实时优先
Kubernetes 的 kube-scheduler 从 1.19 开始稳定支持调度框架,开发者可以通过插件扩展队列排序、过滤、打分、预留和绑定等阶段。实时业务若默认插件不够用,可以自定义 QueueSort 或 Score 插件。QueueSort 决定调度队列中 Pod 的出队顺序,默认的 PrioritySort 已按优先级排列,但实时业务可能还希望在同一优先级中按请求到达时间或业务标签二次排序;Score 插件则影响节点选择,可以加入节点实时负载、特殊硬件、网络延迟等维度。
下面的 KubeSchedulerConfiguration 示例展示了一个名为 realtime-scheduler 的调度器配置,启用了自定义的 RealTimeLoadAware 打分插件,并保留默认的优先级抢占能力。该插件可以在 Score 阶段根据节点实时请求负载和目标利用率打分,避免将实时 Pod 调度到已经高负载的节点。插件需要提前部署到调度器容器中,并注册到插件目录。
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: realtime-scheduler
plugins:
queueSort:
enabled:
- name: PrioritySort
postFilter:
enabled:
- name: DefaultPreemption
score:
enabled:
- name: NodeResourcesFit
weight: 20
- name: RealTimeLoadAware
weight: 80
pluginConfig:
- name: RealTimeLoadAware
args:
targetLoad: 60
若要实现完整插件,需要编写 Go 程序实现 framework.ScorePlugin 接口。核心逻辑可以是根据节点注解或监控数据获取当前 CPU 使用率,低于目标负载给高分,高于目标负载降低分数。插件注册后,需要在调度器配置中引用。与修改 kube-scheduler 源码相比,插件方式避免了分支维护成本,更适合生产环境迭代。
四、节点隔离、拓扑分布与实时业务部署建议
实时业务对网络抖动和单点故障非常敏感,因此只靠优先级和 QoS 还不够,需要从节点和拓扑层面进行隔离。可以使用节点池策略,将实时业务节点与批处理节点通过标签区分,例如 tier=realtime 和 tier=batch,然后在实时 Pod 上配置 nodeSelector 或 nodeAffinity。这样实时业务不会与计算密集的批处理任务争抢同一批节点,也能避免抢占频繁发生。
拓扑分布约束也很关键。例如一个实时网关有多个副本,如果调度器将它们集中在同一个可用区,该可用区故障会导致服务中断。使用 topologySpreadConstraints 可以强制副本在 zone 和 node 之间分散。结合优先级调度后,高优先生效的前提仍然是满足硬性约束;如果拓扑约束无法满足,Pod 会保持 Pending。因此需要在资源容量和容灾要求之间做平衡。
apiVersion: apps/v1
kind: Deployment
metadata:
name: realtime-gateway
spec:
replicas: 6
selector:
matchLabels:
app: realtime-gateway
template:
metadata:
labels:
app: realtime-gateway
spec:
priorityClassName: realtime-high
nodeSelector:
tier: realtime
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: realtime-gateway
containers:
- name: gateway
image: nginx:1.25
resources:
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "1"
memory: "2Gi"
此外,如果实时业务节点需要独占 CPU 或使用 NUMA 拓扑,可以结合静态 CPU 管理策略和 Topology Manager。这些能力在 Kubernetes 中通过 kubelet 配置生效,调度器会收到节点的拓扑资源信息。配置节点隔离时,要同时考虑污点和容忍:实时节点可以打上专用污点,只允许实时 Pod 调度;批处理节点则避免实时业务落入。整体思路是让优先级决策发生在正确节点集合之上,而不是等抢占发生时再补救。
Kubernetes优先级调度实时业务修改时间:2026-08-28 21:42:22