RayJob 快速入门#

先决条件#

  • KubeRay v0.6.0 或更高版本

    • KubeRay v0.6.0 或 v1.0.0: Ray 1.10 或更高版本。

    • 强烈推荐使用 KubeRay v1.1.1:Ray 2.8.0 或更高版本。本文档主要针对 KubeRay v1.1.1。

什么是 RayJob?#

一个 RayJob 管理两个方面:

  • RayCluster:RayCluster 自定义资源管理 Ray 集群中的所有 Pod,包括一个头 Pod 和多个工作 Pod。

  • 任务:Kubernetes 任务运行 ray job submit 以将 Ray 任务提交到 RayCluster。

RayJob 提供了什么?#

使用 RayJob,KubeRay 会在 RayCluster 准备好时自动创建集群并提交作业。您还可以配置 RayJob 在 Ray 作业完成后自动删除 RayCluster。

为了更好地理解以下内容,您应该了解以下区别:

  • RayJob: KubeRay 提供的 Kubernetes 自定义资源定义。

  • Ray 作业:Ray 作业是一个可以在远程 Ray 集群上运行的打包 Ray 应用程序。更多详情请参见 这份文档

  • 提交者:提交者是一个 Kubernetes Job,它运行 ray job submit 来向 RayCluster 提交一个 Ray 作业。

RayJob 配置#

  • RayCluster 配置

    • rayClusterSpec - 定义了运行 Ray 作业的 RayCluster 自定义资源。

  • Ray 作业配置

    • entrypoint - 提交者运行 ray job submit --address ... --submission-id ... -- $entrypoint 将 Ray 作业提交到 RayCluster。

    • runtimeEnvYAML (可选): 一个描述 Ray 作业运行所需依赖项的运行时环境,包括文件、包、环境变量等。将配置作为多行 YAML 字符串提供。示例:

      spec:
        runtimeEnvYAML: |
          pip:
            - requests==2.26.0
            - pendulum==2.1.2
          env_vars:
            KEY: "VALUE"
      

    更多详情请参见 运行时环境(KubeRay 版本 1.0.0 新增)

    • jobId (可选): 定义 Ray 作业的提交 ID。如果未提供,KubeRay 会自动生成一个。有关提交 ID 的更多详情,请参阅 Ray 作业 CLI API 参考

    • metadata (可选): 关于 --metadata-json 选项的更多详情,请参阅 Ray Jobs CLI API 参考

    • entrypointNumCpus / entrypointNumGpus / entrypointResources (可选): 更多详情请参阅 Ray Jobs CLI API 参考

  • 提交配置

    • submissionMode (可选): submissionMode 指定了 RayJob 如何将 Ray 作业提交到 RayCluster。在 “K8sJobMode” 模式下,KubeRay 操作员创建一个提交者 Kubernetes Job 来提交 Ray 作业。在 “HTTPMode” 模式下,KubeRay 操作员向 RayCluster 发送请求以创建 Ray 作业。默认值为 “K8sJobMode”。

    • submitterPodTemplate (可选): 定义提交者 Kubernetes Job 的 Pod 模板。仅当 submissionMode 为 “K8sJobMode” 时,此字段才有效。

      • RAY_DASHBOARD_ADDRESS - KubeRay 操作员将此环境变量注入到提交者 Pod 中。其值为 $HEAD_SERVICE:$DASHBOARD_PORT

      • RAY_JOB_SUBMISSION_ID - KubeRay 操作员将此环境变量注入提交者 Pod 中。该值是 RayJob 的 RayJob.Status.JobId

      • 示例: ray job submit --address=http://$RAY_DASHBOARD_ADDRESS --submission-id=$RAY_JOB_SUBMISSION_ID ...

      • 更多详情请参见 ray-job.sample.yaml

  • 自动资源清理

    • shutdownAfterJobFinishes (可选): 决定在 Ray 作业完成后是否回收 RayCluster。默认值为 false。

    • ttlSecondsAfterFinished (可选): 仅在 shutdownAfterJobFinishes 为 true 时有效。KubeRay 操作员在 Ray 作业完成后 ttlSecondsAfterFinished 秒删除 RayCluster 和提交者。默认值为 0。

    • activeDeadlineSeconds (可选): 如果 RayJob 在 activeDeadlineSeconds 内没有将 JobDeploymentStatus 转换为 CompleteFailed,KubeRay 操作员会将 JobDeploymentStatus 转换为 Failed,并引用 DeadlineExceeded 作为原因。

示例:使用 RayJob 运行一个简单的 Ray 作业#

步骤 1:使用 Kind 创建一个 Kubernetes 集群#

kind create cluster --image=kindest/node:v1.26.0

步骤 2:安装 KubeRay 操作员#

按照 RayCluster 快速入门 通过 Helm 仓库安装最新稳定的 KubeRay 操作员。

步骤 3:安装 RayJob#

kubectl apply -f https://raw.githubusercontent.com/ray-project/kuberay/v1.1.1/ray-operator/config/samples/ray-job.sample.yaml

步骤 4:验证 Kubernetes 集群状态#

# Step 4.1: List all RayJob custom resources in the `default` namespace.
kubectl get rayjob

# [Example output]
# NAME            JOB STATUS   DEPLOYMENT STATUS   START TIME             END TIME   AGE
# rayjob-sample                Running             2024-03-02T19:09:15Z              96s

# Step 4.2: List all RayCluster custom resources in the `default` namespace.
kubectl get raycluster

# [Example output]
# NAME                             DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
# rayjob-sample-raycluster-tlsxc   1                 1                   400m   0        0      ready    91m

# Step 4.3: List all Pods in the `default` namespace.
# The Pod created by the Kubernetes Job will be terminated after the Kubernetes Job finishes.
kubectl get pods

# [Example output]
# kuberay-operator-7456c6b69b-rzv25                         1/1     Running     0          3m57s
# rayjob-sample-lk9jx                                       0/1     Completed   0          2m49s => Pod created by a Kubernetes Job
# rayjob-sample-raycluster-9c546-head-gdxkg                 1/1     Running     0          3m46s
# rayjob-sample-raycluster-9c546-worker-small-group-nfbxm   1/1     Running     0          3m46s

# Step 4.4: Check the status of the RayJob.
# The field `jobStatus` in the RayJob custom resource will be updated to `SUCCEEDED` and `jobDeploymentStatus`
# should be `Complete` once the job finishes.
kubectl get rayjobs.ray.io rayjob-sample -o jsonpath='{.status.jobStatus}'
# [Expected output]: "SUCCEEDED"

kubectl get rayjobs.ray.io rayjob-sample -o jsonpath='{.status.jobDeploymentStatus}'
# [Expected output]: "Complete"

KubeRay 操作符根据 rayClusterSpec 创建一个 RayCluster 自定义资源和一个提交器 Kubernetes Job,用于将 Ray 作业提交到 RayCluster。在这个例子中,entrypointpython /home/ray/samples/sample_code.py,而 sample_code.py 是一个存储在 Kubernetes ConfigMap 中的 Python 脚本,该 ConfigMap 挂载到 RayCluster 的头 Pod 上。由于 shutdownAfterJobFinishes 的默认值为 false,因此当 Ray 作业完成时,KubeRay 操作符不会删除 RayCluster 或提交器。

步骤 5:检查 Ray 作业的输出#

kubectl logs -l=job-name=rayjob-sample

# [Example output]
# 2023-08-21 17:08:22,530 INFO cli.py:27 -- Job submission server address: http://rayjob-sample-raycluster-9c546-head-svc.default.svc.cluster.local:8265
# 2023-08-21 17:08:23,726 SUCC cli.py:33 -- ------------------------------------------------
# 2023-08-21 17:08:23,727 SUCC cli.py:34 -- Job 'rayjob-sample-5ntcr' submitted successfully
# 2023-08-21 17:08:23,727 SUCC cli.py:35 -- ------------------------------------------------
# 2023-08-21 17:08:23,727 INFO cli.py:226 -- Next steps
# 2023-08-21 17:08:23,727 INFO cli.py:227 -- Query the logs of the job:
# 2023-08-21 17:08:23,727 INFO cli.py:229 -- ray job logs rayjob-sample-5ntcr
# 2023-08-21 17:08:23,727 INFO cli.py:231 -- Query the status of the job:
# 2023-08-21 17:08:23,727 INFO cli.py:233 -- ray job status rayjob-sample-5ntcr
# 2023-08-21 17:08:23,727 INFO cli.py:235 -- Request the job to be stopped:
# 2023-08-21 17:08:23,728 INFO cli.py:237 -- ray job stop rayjob-sample-5ntcr
# 2023-08-21 17:08:23,739 INFO cli.py:245 -- Tailing logs until the job exits (disable with --no-wait):
# 2023-08-21 17:08:34,288 INFO worker.py:1335 -- Using address 10.244.0.6:6379 set in the environment variable RAY_ADDRESS
# 2023-08-21 17:08:34,288 INFO worker.py:1452 -- Connecting to existing Ray cluster at address: 10.244.0.6:6379...
# 2023-08-21 17:08:34,302 INFO worker.py:1633 -- Connected to Ray cluster. View the dashboard at http://10.244.0.6:8265
# test_counter got 1
# test_counter got 2
# test_counter got 3
# test_counter got 4
# test_counter got 5
# 2023-08-21 17:08:46,040 SUCC cli.py:33 -- -----------------------------------
# 2023-08-21 17:08:46,040 SUCC cli.py:34 -- Job 'rayjob-sample-5ntcr' succeeded
# 2023-08-21 17:08:46,040 SUCC cli.py:35 -- -----------------------------------

Python 脚本 sample_code.pyentrypoint 使用,是一个简单的 Ray 脚本,执行计数器的增量函数 5 次。

步骤 6:删除 RayJob#

kubectl delete -f https://raw.githubusercontent.com/ray-project/kuberay/v1.1.1/ray-operator/config/samples/ray-job.sample.yaml

步骤 7:创建一个 RayJob,并将 shutdownAfterJobFinishes 设置为 true#

kubectl apply -f https://raw.githubusercontent.com/ray-project/kuberay/v1.1.1/ray-operator/config/samples/ray-job.shutdown.yaml

ray-job.shutdown.yaml 定义了一个 RayJob 自定义资源,其中 shutdownAfterJobFinishes: truettlSecondsAfterFinished: 10。因此,KubeRay 操作员在 Ray 作业完成后 10 秒删除 RayCluster。请注意,提交者作业不会被删除,因为它包含 ray 作业日志,并且在完成后不使用任何集群资源。此外,当 RayJob 最终由于其所有者引用回 RayJob 而被删除时,提交者作业将始终被清理。

步骤 8:检查 RayJob 状态#

# Wait until `jobStatus` is `SUCCEEDED` and `jobDeploymentStatus` is `Complete`.
kubectl get rayjobs.ray.io rayjob-sample-shutdown -o jsonpath='{.status.jobDeploymentStatus}'
kubectl get rayjobs.ray.io rayjob-sample-shutdown -o jsonpath='{.status.jobStatus}'

步骤 9:检查 KubeRay 操作符是否删除 RayCluster#

# List the RayCluster custom resources in the `default` namespace. The RayCluster
# associated with the RayJob `rayjob-sample-shutdown` should be deleted.
kubectl get raycluster

步骤 10:清理#

# Step 10.1: Delete the RayJob
kubectl delete -f https://raw.githubusercontent.com/ray-project/kuberay/v1.1.1/ray-operator/config/samples/ray-job.shutdown.yaml

# Step 10.2: Delete the KubeRay operator
helm uninstall kuberay-operator

# Step 10.3: Delete the Kubernetes cluster
kind delete cluster

下一步#