Skip to main content

什么是RayJob

RayJobKubeRay提供的一种Kubernetes自定义资源(CRD),用于简化Ray任务的提交和管理流程。RayJob管理两个关键方面:

  • RayCluster管理:自动创建和管理RayCluster资源,包括Head NodeWorker Nodes
  • 任务提交:在集群就绪后自动提交Ray任务,并跟踪任务执行状态。

相比手动管理RayCluster和任务提交,RayJob提供了以下优势:

  • 自动化:无需手动创建集群和提交任务,KubeRay Operator会自动处理整个生命周期。
  • 资源优化:任务完成后可自动清理集群资源,避免资源浪费。
  • 易于管理:通过单一的YAML配置文件管理整个任务流程。
  • 重试机制:支持任务失败后的自动重试。

完整示例配置

以下是一个功能完整的RayJob配置示例,展示了所有主要配置项:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: rayjob-sample
namespace: default
labels:
app: ray-job
version: v1
spec:
# ==================== 任务提交配置 ====================

# 任务入口命令
entrypoint: python /home/ray/samples/sample_code.py

# 任务提交模式,默认为K8sJobMode
submissionMode: K8sJobMode

# 任务ID,如果不设置会自动生成
# jobId: "custom-job-id-12345"

# 任务元数据
metadata:
app: "sample-ray-job"
version: "1.0"

# 运行时环境配置
runtimeEnvYAML: |
pip:
- requests==2.26.0
- pendulum==2.1.2
env_vars:
counter_name: "test_counter"
LOG_LEVEL: "INFO"

# 入口任务资源配置
# entrypointNumCpus: 1.0
# entrypointNumGpus: 0
# entrypointResources: '{"custom_resource": 1}'

# ==================== 重试和超时配置 ====================

# 任务失败后的重试次数,每次重试都会创建新的RayCluster
backoffLimit: 0

# 任务超时时间(秒),超时后任务会被标记为失败
# activeDeadlineSeconds: 600

# ==================== 集群选择配置 ====================

# 使用标签选择器选择已有的RayCluster,而不是创建新集群
# clusterSelector:
# ray.io/cluster: "existing-cluster"

# ==================== 资源清理配置 ====================

# 任务完成后是否自动删除RayCluster
shutdownAfterJobFinishes: false

# 任务完成后延迟删除时间(秒),仅在shutdownAfterJobFinishes为true时有效
ttlSecondsAfterFinished: 0

# ==================== 暂停配置 ====================

# 是否暂停任务,为true时不会创建RayCluster
suspend: false

# ==================== 提交器配置 ====================

# 提交器Job的配置
submitterConfig:
# 提交器Job的重试次数
backoffLimit: 2

# 自定义提交器Pod模板(可选)
# submitterPodTemplate:
# spec:
# restartPolicy: Never
# containers:
# - name: ray-job-submitter
# image: rayproject/ray:latest-py311-cpu
# resources:
# requests:
# cpu: "500m"
# memory: "512Mi"
# limits:
# cpu: "1"
# memory: "1Gi"

# ==================== RayCluster配置 ====================

rayClusterSpec:
# Ray版本,应与容器镜像中的Ray版本匹配
rayVersion: '2.9.0'

# ===== Head节点配置 =====
headGroupSpec:
# Ray启动参数
rayStartParams:
dashboard-host: '0.0.0.0'
block: 'true'

# Head Pod模板
template:
metadata:
labels:
app: ray-head
ray.io/cluster: rayjob-sample
spec:
containers:
- name: ray-head
image: rayproject/ray:latest-py311-cpu
imagePullPolicy: IfNotPresent

# 容器端口
ports:
- containerPort: 6379
name: gcs-server
- containerPort: 8265
name: dashboard
- containerPort: 10001
name: client

# 资源限制
resources:
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "2"
memory: "4Gi"

# 挂载代码文件
volumeMounts:
- name: code-sample
mountPath: /home/ray/samples

# 卷配置
volumes:
- name: code-sample
configMap:
name: ray-job-code-sample
items:
- key: sample_code.py
path: sample_code.py

# ===== Worker节点组配置 =====
workerGroupSpecs:
- groupName: small-group
replicas: 2
minReplicas: 1
maxReplicas: 5

# Ray启动参数
rayStartParams:
block: 'true'

# Worker Pod模板
template:
metadata:
labels:
app: ray-worker
ray.io/cluster: rayjob-sample
ray.io/group: small-group
spec:
initContainers:
# 等待Head节点就绪的初始化容器
- name: wait-for-head
image: busybox:1.28
command:
- sh
- -c
- |
until nslookup $RAY_IP.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do
echo "Waiting for head service..."
sleep 2
done

containers:
- name: ray-worker
image: rayproject/ray:latest-py311-cpu
imagePullPolicy: IfNotPresent

# 资源限制
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1"
memory: "2Gi"

# 生命周期配置
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- ray stop
说明

以上配置示例基于KubeRay v1.0.0+Ray 2.9.0+版本。不同版本的配置项可能有所差异,请根据实际使用的版本进行调整。

RayJob核心配置项

Spec级别配置

RayJobspec字段定义了任务的核心配置,以下是各配置项的详细说明:

配置项默认值说明
entrypoint-Ray任务的入口命令,相当于ray job submit命令的最后一个参数。例如:python train.pypython -m module.main
submissionModeK8sJobMode任务提交模式。可选值:
- K8sJobMode:通过Kubernetes Job提交任务(推荐)
- HTTPMode:通过HTTP请求提交任务
- InteractiveMode:等待用户手动提交任务(alpha阶段)
- SidecarMode:通过Sidecar容器提交任务
jobId自动生成任务提交ID。如果不设置,KubeRay会自动生成一个唯一ID。手动设置可用于任务追踪和幂等性保证
metadata-任务元数据,以键值对形式存储,可用于任务分类和检索
runtimeEnvYAML-运行时环境配置,以多行YAML字符串形式提供。支持配置pip包、环境变量、工作目录等。详见Ray运行时环境文档
backoffLimit0任务失败后的最大重试次数。每次重试会创建新的RayCluster。设置为0表示不重试
activeDeadlineSeconds-任务的最大执行时间(秒)。超过该时间后,任务会被标记为失败,状态变为Failed,原因为DeadlineExceeded
suspendfalse是否暂停任务。为true时,KubeRay不会创建RayCluster;如果集群已存在,会被删除。适用于临时暂停任务的场景
shutdownAfterJobFinishesfalse任务完成后是否自动删除RayCluster。设置为true可节省资源
ttlSecondsAfterFinished0任务完成后延迟删除RayCluster的时间(秒)。仅在shutdownAfterJobFinishestrue时生效
rayClusterSpec-RayCluster的配置规格,定义集群的节点配置、资源分配等。与clusterSelector互斥
clusterSelector-通过标签选择器选择已有的RayCluster运行任务,而不是创建新集群。与rayClusterSpec互斥

入口任务资源配置

配置项默认值说明
entrypointNumCpus-为入口任务保留的CPU核数。相当于ray job submit --entrypoint-num-cpus参数
entrypointNumGpus-为入口任务保留的GPU卡数。相当于ray job submit --entrypoint-num-gpus参数
entrypointResources-为入口任务保留的自定义资源,以JSON字符串形式提供。例如:'{"custom_resource": 1}'

提交器配置

submissionModeK8sJobMode时(默认值),KubeRay会创建一个Kubernetes Job来提交Ray任务。以下配置用于自定义提交器的行为:

配置项默认值说明
submitterConfig.backoffLimit2提交器Job的重试次数。注意与spec.backoffLimit的区别:
- spec.backoffLimit:整个RayJob的重试次数,每次重试创建新集群
- submitterConfig.backoffLimit:单次任务提交失败时的重试次数
submitterPodTemplate-自定义提交器Pod的模板。可以自定义镜像、资源限制、环境变量等。KubeRay会自动注入RAY_DASHBOARD_ADDRESSRAY_JOB_SUBMISSION_ID环境变量

删除策略配置(Alpha功能)

deletionStrategy字段提供了更灵活的资源清理策略。该功能需要启用RayJobDeletionPolicy特性开关。

基于规则的删除策略(推荐)

通过deletionRules定义多个删除规则,每个规则包含触发条件和删除动作:

deletionStrategy:
deletionRules:
# 规则1:任务成功后立即删除Worker节点
- policy: DeleteWorkers
condition:
jobStatus: SUCCEEDED
ttlSeconds: 0

# 规则2:任务成功后300秒删除整个集群
- policy: DeleteCluster
condition:
jobStatus: SUCCEEDED
ttlSeconds: 300

# 规则3:任务失败后立即删除整个RayJob资源
- policy: DeleteSelf
condition:
jobStatus: FAILED
ttlSeconds: 0

删除规则配置说明:

配置项可选值默认值说明
policyDeleteCluster
DeleteWorkers
DeleteSelf
DeleteNone
-删除策略类型:
- DeleteCluster:删除整个RayCluster及其所有Pod
- DeleteWorkers:仅删除Worker Pod,保留Head Pod
- DeleteSelf:删除RayJob及其关联的所有资源
- DeleteNone:不删除任何资源
condition.jobStatusSUCCEEDED
FAILED
-触发删除的任务状态。与jobDeploymentStatus互斥,必须设置其中一个
condition.jobDeploymentStatusFailed-触发删除的部署状态。用于任务提交失败等基础设施层面的清理
condition.ttlSeconds-0达到指定状态后延迟删除的秒数。默认为0表示立即删除
注意
  • deletionRules模式与shutdownAfterJobFinishesttlSecondsAfterFinished不兼容,不能同时使用。
  • 使用deletionRules时,需要为每个条件设置独立的ttlSeconds
  • 多个规则同时满足条件时,影响最大的规则(如DeleteSelf)会优先执行。

传统删除策略(已弃用)

通过onSuccessonFailure定义任务成功和失败时的删除策略。该方式将在v1.6.0版本中移除,建议迁移到deletionRules

deletionStrategy:
onSuccess:
policy: DeleteCluster
onFailure:
policy: DeleteSelf

RayCluster配置

rayClusterSpec字段定义了要创建的RayCluster的完整规格。这是RayJob中最复杂的部分,包含了集群的所有配置细节。

RayCluster基本配置

配置项默认值说明
rayVersion-Ray版本号,应与容器镜像中的Ray版本一致。例如:2.9.0。该字段为必填项
headGroupSpec-Head节点的配置规格,包括Pod模板、资源限制等。该字段为必填项
workerGroupSpecs-Worker节点组的配置列表。可以定义多个不同配置的Worker

HeadGroupSpec配置

Head节点是Ray集群的控制节点,负责调度任务、管理元数据和提供Dashboard服务。

配置项默认值说明
serviceTypeClusterIPHead节点服务类型。可选值:ClusterIPNodePortLoadBalancer
rayStartParams-ray start命令的参数。常用参数:
- dashboard-hostDashboard监听地址,设置为0.0.0.0可从外部访问
- block:是否阻塞,建议设置为true
- num-cpus:手动指定CPU数量
- num-gpus:手动指定GPU数量
template-Head Pod的模板,定义容器镜像、资源限制、卷挂载等。该字段为必填项

WorkerGroupSpec配置

Worker节点负责实际的计算任务。可以定义多个Worker组,每组有不同的资源配置。

配置项默认值说明
groupName-Worker组的名称,在同一集群内必须唯一。该字段为必填项
replicas1Worker节点的初始副本数
minReplicas0最小副本数,用于自动伸缩
maxReplicas2147483647最大副本数,用于自动伸缩
rayStartParams-ray start命令的参数,与Head节点类似
template-Worker Pod的模板。该字段为必填项

PodTemplate常用配置

HeadWorker节点的template字段都是标准的Kubernetes PodTemplateSpec,以下是常用配置:

容器配置:

配置项说明
image容器镜像
imagePullPolicy镜像拉取策略,可选:AlwaysIfNotPresentNever
resources.requests资源请求量,用于调度决策
resources.limits资源限制量,超过限制会触发OOMKilledCPU限流
ports容器端口列表,Head节点通常需要暴露6379GCS)、8265Dashboard)、10001Client)端口
volumeMounts卷挂载配置,用于挂载代码文件、数据集等
env环境变量列表
lifecycle生命周期钩子,如preStop用于优雅停止

Pod配置:

配置项说明
volumes卷定义,支持ConfigMapSecretPVCEmptyDir
nodeSelector节点选择器,用于将Pod调度到特定节点
tolerations污点容忍,配合节点污点使用
affinity亲和性和反亲和性规则
serviceAccountName服务账户名称,用于Pod的权限控制
imagePullSecrets镜像拉取密钥
initContainers初始化容器,在主容器启动前执行

配置示例详解

示例1:基础任务提交

最简单的RayJob配置,创建集群并运行任务:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: simple-job
spec:
entrypoint: python /home/ray/test.py

rayClusterSpec:
rayVersion: '2.9.0'

headGroupSpec:
rayStartParams:
dashboard-host: '0.0.0.0'
template:
spec:
containers:
- name: ray-head
image: rayproject/ray:latest-py311-cpu
resources:
requests:
cpu: "1"
memory: "2Gi"

workerGroupSpecs:
- groupName: workers
replicas: 2
template:
spec:
containers:
- name: ray-worker
image: rayproject/ray:latest-py311-cpu
resources:
requests:
cpu: "1"
memory: "2Gi"

示例2:带运行时环境的任务

配置任务运行时需要的Python包和环境变量:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: job-with-runtime-env
spec:
entrypoint: python /home/ray/train.py

# 运行时环境配置
runtimeEnvYAML: |
pip:
- torch==2.0.0
- transformers==4.30.0
- datasets==2.12.0
env_vars:
MODEL_NAME: "bert-base-uncased"
BATCH_SIZE: "32"
LEARNING_RATE: "2e-5"
working_dir: "/home/ray/workspace"

rayClusterSpec:
rayVersion: '2.9.0'
# ... 集群配置省略 ...

示例3:自动清理资源

任务完成后自动删除集群,节省资源:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: job-with-cleanup
spec:
entrypoint: python /home/ray/batch_inference.py

# 任务完成后自动删除集群
shutdownAfterJobFinishes: true

# 延迟10分钟后删除,留出时间查看日志
ttlSecondsAfterFinished: 600

rayClusterSpec:
rayVersion: '2.9.0'
# ... 集群配置省略 ...

示例4:使用已有集群

选择已存在的RayCluster运行任务,而不是创建新集群:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: job-on-existing-cluster
spec:
entrypoint: python /home/ray/analyze.py

# 通过标签选择已有集群
clusterSelector:
ray.io/cluster-name: "my-existing-cluster"
environment: "production"

# 注意:使用clusterSelector时不需要rayClusterSpec

示例5:GPU训练任务

配置使用GPU资源的训练任务:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: gpu-training-job
spec:
entrypoint: python /home/ray/train_llm.py

# 为入口任务分配GPU
entrypointNumGpus: 1

runtimeEnvYAML: |
pip:
- torch==2.0.0+cu118
- accelerate==0.20.0

rayClusterSpec:
rayVersion: '2.9.0'

headGroupSpec:
rayStartParams:
dashboard-host: '0.0.0.0'
num-gpus: '0' # Head节点不需要GPU
template:
spec:
containers:
- name: ray-head
image: rayproject/ray:latest-py311-cpu-gpu
resources:
requests:
cpu: "2"
memory: "4Gi"

workerGroupSpecs:
- groupName: gpu-workers
replicas: 4
minReplicas: 2
maxReplicas: 8
rayStartParams:
num-gpus: '1'
template:
spec:
containers:
- name: ray-worker
image: rayproject/ray:latest-py311-cpu-gpu
resources:
requests:
cpu: "4"
memory: "16Gi"
nvidia.com/gpu: "1"
limits:
nvidia.com/gpu: "1"

# GPU节点选择器
nodeSelector:
nvidia.com/gpu.present: "true"

# 容忍GPU节点污点
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule

示例6:高级删除策略

使用新的基于规则的删除策略,实现分阶段资源清理:

apiVersion: ray.io/v1
kind: RayJob
metadata:
name: job-with-deletion-rules
spec:
entrypoint: python /home/ray/process.py

# 高级删除策略(需要启用RayJobDeletionPolicy特性开关)
deletionStrategy:
deletionRules:
# 成功时:立即删除Worker,保留Head用于调试
- policy: DeleteWorkers
condition:
jobStatus: SUCCEEDED
ttlSeconds: 0

# 成功时:5分钟后删除整个集群
- policy: DeleteCluster
condition:
jobStatus: SUCCEEDED
ttlSeconds: 300

# 失败时:保留30分钟用于排查问题
- policy: DeleteSelf
condition:
jobStatus: FAILED
ttlSeconds: 1800

rayClusterSpec:
rayVersion: '2.9.0'
# ... 集群配置省略 ...

参考资料