SkyPilot 优先级调度与抢占实战:利用 Kubernetes PriorityClass 实现高优任务抢占

发布时间:2026/9/16 21:14:42
SkyPilot 优先级调度与抢占实战:利用 Kubernetes PriorityClass 实现高优任务抢占 SkyPilot 优先级调度与抢占实战利用 Kubernetes PriorityClass 实现高优任务抢占【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilotSkyPilot 支持基于优先级的调度priority-based scheduling、抢占preemption与重新排队re-queuing。当 Kubernetes 集群资源不足时高优先级任务可以抢占低优先级任务的 Pod被抢占的任务会在资源释放后由 SkyPilot 自动恢复运行。本文将基于 kubernetes-priorities.rst 的核心流程结合仓库源码深入讲解 PriorityClass 的创建、SkyPilot 任务优先级配置、抢占与恢复机制以及需要注意的限制。注意优先级与抢占功能仅支持 Kubernetes基础设施不适用于公有云 VM 等环境。一、整体思路三步启用优先级调度要在 SkyPilot 中启用基于优先级的调度只需完成三个步骤在 Kubernetes 集群中创建 PriorityClass优先级类在 SkyPilot 任务的 YAML 中通过config.kubernetes.pod_config.spec.priorityClassName字段为任务指定优先级类使用sky jobs launch将任务作为 managed job 启动。完成上述配置后当资源受限时高优先级任务将抢占低优先级任务的资源保证关键作业优先运行。下面以high-priority和low-priority两个优先级类为例给出完整可运行的示例。二、Step 1创建 Kubernetes PriorityClass在集群中创建两个 PriorityClass。Kubernetes 原生的 PriorityClass 定义在scheduling.k8s.io/v1API 组中核心字段包括value优先级数值数值越大优先级越高取值范围 -2^31 到 10^9globalDefault是否作为集群默认优先级类整个集群中最多只能有一个为truedescription可读性说明文本preemptionPolicy可选PreemptLowerPriority默认允许抢占低优先级 Pod或Never禁止抢占。以下priorities.yaml创建两个优先级类high-priorityvalue 200用于关键任务low-priorityvalue 100作为全局默认类用于后台任务# priorities.yaml apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 200 globalDefault: false description: High priority class for critical jobs --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: low-priority value: 100 globalDefault: true description: Low priority class for background jobs更高的value意味着更高的优先级。你可以按需创建任意数量的优先级类例如为不同业务线或不同团队设置不同档位。将优先级类应用到集群$ kubectl apply -f priorities.yaml三、Step 2在 SkyPilot 任务中设置优先级SkyPilot 任务通过顶层config.kubernetes.pod_config字段将任意 Pod 配置注入集群 Pod。在 YAML 中写入spec.priorityClassName即可为该任务指定优先级类。下面使用两个简单的计数任务演示high-priority-job.yaml每秒打印一次计数共 1000 次并绑定high-priority类# high-priority-job.yaml resources: infra: k8s cpus: 4 run: | python -c import time for i in range(1000): print(fHigh priority counter: {i}) time.sleep(1) config: kubernetes: pod_config: spec: priorityClassName: high-priority对应的低优先级任务low-priority-job.yaml结构完全一致仅将priorityClassName改为low-priority# low-priority-job.yaml resources: infra: k8s cpus: 4 run: | python -c import time for i in range(1000): print(fLow priority counter: {i}) time.sleep(1) config: kubernetes: pod_config: spec: priorityClassName: low-priorityTip观察抢占行为的关键请将resources.cpus设置为“一个任务运行后集群就没有剩余 CPU 留给另一个任务”的数值。你可以用kubectl get nodes查看集群的 CPU 总量据此确定该值。关于 pod_config 的注入机制config.kubernetes.pod_config不仅能设置优先级类还能注入imagePullSecrets、tolerations、hostNetwork等任意 Kubernetes Pod 字段。在 sky/provision/kubernetes/utils.py 的resolve_effective_pod_config中SkyPilot 会从全局配置~/.sky/config.yaml与任务级配置中合并出“有效的 pod_config”随后 combine_pod_config_fields 将其合并进渲染后的 Ray 集群 YAML——合并语义为“新字段追加、已有字段更新嵌套对象递归合并、列表追加”。配置校验方面sky/provision/kubernetes/utils.py 中的check_pod_config会调用PodValidator.validate验证 pod_config 的合法性而在 sky/utils/schemas.py 的配置模式中pod_config允许任意键注释明确说明“Allow arbitrary keys since validating pod spec is hard”因此你可以放心写入任意 Kubernetes Pod spec 字段。最终渲染模板 sky/templates/kubernetes-ray.yml.j2 中还会把优先级类记录为skypilot-priority-class注解供后续调度与观测使用。四、Step 3以 managed job 方式启动并观察抢占使用sky jobs launch将任务作为 managed job 启动。先启动低优先级任务$ sky jobs launch low-priority-job.yaml随后启动高优先级任务$ sky jobs launch high-priority-job.yaml用sky jobs queue查看任务状态可以看到高优先级任务立即开始运行低优先级任务被抢占$ sky jobs queue Fetching managed job statuses... Managed jobs In progress tasks: 1 RECOVERING, 1 RUNNING ID NAME RESOURCES SUBMITTED TOT. DURATION #RECOVERIES STATUS 2 sky-0232-romilb 1x[CPU:4] 5 mins ago 5m 35s 0 RUNNING 1 sky-0d6f-romilb 1x[CPU:4] 7 mins ago 7m 13s 1 RECOVERING此时低优先级任务进入RECOVERING状态SkyPilot 会在资源可用时自动将其重启。待高优先级任务运行完成后低优先级任务自动恢复运行$ sky jobs queue Fetching managed job statuses... Managed jobs No in-progress managed jobs. ID NAME RESOURCES SUBMITTED TOT. DURATION #RECOVERIES STATUS 2 sky-0232-romilb 1x[CPU:4] 23 mins ago 17m 22s 0 SUCCEEDED 1 sky-0d6f-romilb 1x[CPU:4] 25 mins ago 23m 47s 1 RUNNING从输出可以看到高优先级任务ID 2以 0 次恢复直接SUCCEEDED而低优先级任务ID 1经历 1 次恢复后继续运行#RECOVERIES字段记录了恢复次数。背后的恢复机制managed job 的抢占恢复由 SkyPilot 的任务控制器负责。在 sky/jobs/controller.py 中控制器通过繁忙轮询监控集群状态当检测到 Pod 被抢占/驱逐时触发恢复逻辑并通过 sky/jobs/recovery_strategy.py 中的StrategyExecutor执行清理与重放#RECOVERIES次数即由此记录。任务进入RECOVERING状态后控制器会在资源可用时重新调度该任务。五、优先级与抢占的工作原理抢占行为当集群没有足够资源容纳所有任务时高优先级任务会抢占低优先级任务——即终止低优先级任务的 Pod为高优先级任务腾出空间。该行为由 Kubernetes 调度器基于 Pod 的priorityClassName对应数值判定。自动恢复被抢占的任务不会丢失SkyPilot 会在资源重新可用时自动重新调度。建议在代码中启用 Checkpointing and Recovery断点续训与恢复以减少重复工作。同级优先级优先级相同的任务遵循 SkyPilot 的 默认排队调度行为。非托管集群优先级类同样可以应用于非托管unmanagedSkyPilot 集群但被抢占后不会自动重启。六、限制与注意事项作用域优先级设置仅在单个 Kubernetes 集群内部生效跨集群如多 Kubernetes 上下文之间不存在优先级比较。抢占范围抢占行为取决于集群本身的配置高优先级 Pod可能抢占集群中任何低优先级的 Pod——包括并非由 SkyPilot 管理的其他工作负载。请在共享集群中谨慎设置preemptionPolicy与优先级数值避免影响他人任务。资源估算优先级抢占的前提是 kube-scheduler 能正确感知资源余量。请确保集群节点资源可被准确上报例如通过 Kubernetes 部署配置 正确设置节点可分配资源否则调度器可能无法触发预期的抢占。七、进一步阅读Managed Jobs 使用指南managed job 的完整语义、排队与自动重启行为Checkpointing and Recovery如何在任务代码中实现断点续训减少抢占带来的重复计算SkyPilot 配置参考config.kubernetes命名空间的完整配置项包括pod_config的全局/任务级合并规则Kubernetes 官方文档Pod Priority and PreemptionPriorityClass 与抢占调度器的底层原理Kubernetes 原生概念。通过优先级类 managed job 的组合SkyPilot 团队可以在共享的 Kubernetes 集群上实现“关键任务优先、后台任务让路、被抢占后自动恢复”的混合负载调度让有限的集群资源始终服务于最有价值的作业。【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考