使用 Kueue 对 RayJob 进行组调度和优先级调度#
本指南演示了如何在本地 Kind 集群上使用 Kueue 对 RayJob 进行组调度和优先级调度,以及 KubeRay 和 Kueue 的集成。请参考使用 RayJob 和 Kueue 进行优先级调度和使用 RayJob 和 Kueue 进行组调度了解实际用例。
Kueue#
Kueue 是一个 Kubernetes 原生的作业队列系统,用于管理配额以及作业如何消耗配额。Kueue 决定何时
让作业等待。
允许作业启动,这会触发 Kubernetes 创建 Pod。
抢占作业,这会触发 Kubernetes 删除活动的 Pod。
Kueue 原生支持某些 KubeRay API。具体来说,你可以使用 Kueue 来管理 RayJob 和 RayCluster 消耗的资源。请参阅 Kueue 文档了解更多信息。
步骤 0:创建一个 Kind 集群#
kind create cluster
步骤 1:安装 KubeRay Operator#
按照部署 KubeRay Operator的说明,从 Helm 仓库安装最新的稳定版 KubeRay Operator。
步骤 2:安装 Kueue#
VERSION=v0.6.0
kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
请参阅Kueue 安装了解安装 Kueue 的更多详细信息。Kueue 和 RayJob 之间存在一些限制。请参阅Kueue 的限制了解更多详细信息。
步骤 3:创建 Kueue 资源#
# kueue-resources.yaml
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: "default-flavor"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: "cluster-queue"
spec:
preemption:
withinClusterQueue: LowerPriority
namespaceSelector: {} # Match all namespaces.
resourceGroups:
- coveredResources: ["cpu", "memory"]
flavors:
- name: "default-flavor"
resources:
- name: "cpu"
nominalQuota: 3
- name: "memory"
nominalQuota: 6G
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
namespace: "default"
name: "user-queue"
spec:
clusterQueue: "cluster-queue"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: WorkloadPriorityClass
metadata:
name: prod-priority
value: 1000
description: "Priority class for prod jobs"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: WorkloadPriorityClass
metadata:
name: dev-priority
value: 100
description: "Priority class for development jobs"
YAML 清单配置了
ResourceFlavor
ResourceFlavor
default-flavor
是一个空的 ResourceFlavor,因为 Kubernetes 集群中的计算资源是同质的。换句话说,用户可以请求 1 个 CPU,而无需考虑它是 ARM 芯片还是 x86 芯片。
ClusterQueue
ClusterQueue
cluster-queue
只有一个 ResourceFlavordefault-flavor
,配额为 3 个 CPU 和 6G 内存。ClusterQueue
cluster-queue
有一个抢占策略withinClusterQueue: LowerPriority
。该策略允许不符合其 ClusterQueue 名义配额的待处理 RayJob 抢占 ClusterQueue 中优先级较低的活动 RayJob 自定义资源。
LocalQueue
LocalQueue
user-queue
是default
命名空间中的一个命名空间对象,属于一个 ClusterQueue。通常的做法是为一个组织租户、团队或用户分配一个命名空间。用户将作业提交到 LocalQueue,而不是直接提交到 ClusterQueue。
WorkloadPriorityClass
WorkloadPriorityClass
prod-priority
的值高于 WorkloadPriorityClassdev-priority
。使用prod-priority
优先级类的 RayJob 自定义资源优先于使用dev-priority
优先级类的 RayJob 自定义资源。
创建 Kueue 资源
kubectl apply -f kueue-resources.yaml
步骤 4:使用 Kueue 进行组调度#
Kueue 总是以“组”模式准入工作负载。Kueue 基于“全有或全无”的方式准入工作负载,确保 Kubernetes 永远不会部分配置 RayJob 或 RayCluster。使用组调度策略避免由于低效的工作负载调度造成的计算资源浪费。
从 KubeRay 仓库下载 RayJob YAML 清单。
curl -LO https://raw.githubusercontent.com/ray-project/kuberay/master/ray-operator/config/samples/ray-job.kueue-toy-sample.yaml
在创建 RayJob 之前,修改 RayJob 元数据如下
metadata:
generateName: rayjob-sample-
labels:
kueue.x-k8s.io/queue-name: user-queue
kueue.x-k8s.io/priority-class: dev-priority
创建两个具有相同优先级 dev-priority
的 RayJob 自定义资源。请注意 RayJob 自定义资源的以下重要事项
RayJob 自定义资源包含 1 个 head Pod 和 1 个 worker Pod,每个 Pod 请求 1 个 CPU 和 2G 内存。
该 RayJob 运行一个简单的 Python 脚本,演示一个循环,执行 600 次迭代,打印迭代次数并每次迭代休眠 1 秒。因此,提交的 Kubernetes Job 启动后,RayJob 大约会运行 600 秒。
将 RayJob 的
shutdownAfterJobFinishes
设置为 true,以启用自动清理。此设置会触发 KubeRay 在 RayJob 完成后删除 RayCluster。Kueue 不处理
shutdownAfterJobFinishes
设置为 false 的 RayJob 自定义资源。请参阅Kueue 的限制了解更多详细信息。
kubectl create -f ray-job.kueue-toy-sample.yaml
kubectl create -f ray-job.kueue-toy-sample.yaml
每个 RayJob 自定义资源总共请求 2 个 CPU 和 4G 内存。然而,ClusterQueue 总共只有 3 个 CPU 和 6G 内存。因此,第二个 RayJob 自定义资源保持待处理状态,并且 KubeRay 不会从待处理的 RayJob 创建 Pod,即使剩余资源足以创建一个 Pod。你也可以检查 ClusterQueue
查看可用和已使用的配额
$ kubectl get clusterqueues.kueue.x-k8s.io
NAME COHORT PENDING WORKLOADS
cluster-queue 1
$ kubectl get clusterqueues.kueue.x-k8s.io cluster-queue -o yaml
Status:
Admitted Workloads: 1 # Workloads admitted by queue.
Conditions:
Last Transition Time: 2024-02-28T22:41:28Z
Message: Can admit new workloads
Reason: Ready
Status: True
Type: Active
Flavors Reservation:
Name: default-flavor
Resources:
Borrowed: 0
Name: cpu
Total: 2
Borrowed: 0
Name: memory
Total: 4Gi
Flavors Usage:
Name: default-flavor
Resources:
Borrowed: 0
Name: cpu
Total: 2
Borrowed: 0
Name: memory
Total: 4Gi
Pending Workloads: 1
Reserving Workloads: 1
当第一个 RayJob 自定义资源完成时,Kueue 会准入待处理的 RayJob 自定义资源。检查 RayJob 自定义资源的状态并在它们完成后删除它们
$ kubectl get rayjobs.ray.io
NAME JOB STATUS DEPLOYMENT STATUS START TIME END TIME AGE
rayjob-sample-ckvq4 SUCCEEDED Complete xxxxx xxxxx xxx
rayjob-sample-p5msp SUCCEEDED Complete xxxxx xxxxx xxx
$ kubectl delete rayjob rayjob-sample-ckvq4
$ kubectl delete rayjob rayjob-sample-p5msp
步骤 5:使用 Kueue 进行优先级调度#
此步骤首先创建一个优先级较低的 RayJob dev-priority
,然后创建一个优先级较高的 RayJob prod-priority
。优先级较高的 RayJob prod-priority
优先于优先级较低的 RayJob dev-priority
。Kueue 抢占优先级较低的 RayJob,以准入优先级较高的 RayJob。
如果你完成了上一步,则 RayJob YAML 清单 ray-job.kueue-toy-sample.yaml
应该已经设置为 dev-priority
优先级类。创建一个优先级较低的 RayJob dev-priority
kubectl create -f ray-job.kueue-toy-sample.yaml
在创建优先级较高的 RayJob prod-priority
之前,修改 RayJob 元数据如下
metadata:
generateName: rayjob-sample-
labels:
kueue.x-k8s.io/queue-name: user-queue
kueue.x-k8s.io/priority-class: prod-priority
创建一个优先级较高的 RayJob prod-priority
kubectl create -f ray-job.kueue-toy-sample.yaml
你可以看到 KubeRay operator 删除了属于优先级较低的 RayJob dev-priority
的 Pod,并创建了属于优先级较高的 RayJob prod-priority
的 Pod。