更新时间:2025-08-27 GMT+08:00

Kuberay

插件简介

Kuberay是一个Kubernetes原生插件,用于在Kubernetes集群(包括CCE Standard/Turbo集群)上管理和运行Ray分布式计算框架。Ray是一个高性能的分布式计算库,常用于机器学习、强化学习和数据处理等场景。Kuberay的目标是将Ray与Kubernetes深度集成,使得用户可以轻松地在Kubernetes上部署、管理和扩展Ray Cluster。

Kuberay是一个Kubernetes Operator,它通过自定义资源定义(CRD)管理Ray Cluster的生命周期。它提供了以下核心功能:

  • Ray Cluster的部署:通过声明式的方式定义Ray Cluster的配置,Kuberay会自动创建和管理Ray的Head节点和Worker节点。
  • 自动扩缩容:根据工作负载的需求,动态调整Ray Cluster的Worker Pod数量。
  • 资源管理:与Kubernetes的资源管理机制(如 CPU、内存、GPU 等)无缝集成。
  • 故障恢复:自动监控Ray Cluster的健康状态,并在节点故障时进行恢复。
  • 日志和监控:集成Kubernetes的日志和监控工具,方便用户调试和优化Ray应用。

开源地址https://github.com/ray-project/kuberay

约束限制

  • CCE集群(Standard/Turbo)版本在v1.27及以上。
  • 该特性当前正处于上线阶段,已发布区域请以控制台实际为准

计费说明

如果您需要访问Ray Dashboard,则需要为集群中任一节点绑定EIP。其中,EIP需要涉及一定费用,具体请参见EIP价格计算器

安装插件

  1. 登录CCE控制台,单击集群名称进入集群。
  2. 单击左侧导航栏的“插件中心”,在右侧找到Kuberay插件,单击“安装”
  3. 在安装插件页面,进行“规格配置”。您可以根据需求设置CPU配额和内存配额。

    • CPU配额:CPU资源单位为核,可以使用带单位后缀(m)的整数表达,例如100m。
      表1 CPU配额说明

      参数

      示例

      说明

      CPU申请

      100m

      表示容器的最小CPU需求。

      CPU限制

      500m

      表示容器能使用的CPU最大值。当CPU使用率超出设置的CPU限制值时,该实例可能会被重启进而影响插件的正常使用。

    • 内存配额:内存资源默认单位为字节,可以使用带单位后缀(Mi)的整数来表达,例如100Mi。管理500个Ray Pod需要大约500MB内存,您可以根据内存的使用情况进行调整。
      表2 内存配额说明

      参数

      示例

      说明

      内存申请

      100Mi

      表示容器的最小内存需求。

      内存限制

      500Mi

      表示容器能使用的内存最大值。当内存使用率超出设置的内存限制值时,该实例可能会被重启进而影响插件的正常使用。

  4. 进行“参数配置”,具体请参见表3 参数配置说明

    表3 参数配置说明

    参数

    示例

    说明

    插件安装的命名空间

    default

    表示安装Kuberay插件的命名空间,支持自定义,默认为default。

    批调度器

    不使用

    是否使用外部调度器对Ray Job进行批量调度,默认为不使用。

    • 不使用:表示不使用外部调度器对Ray Job进行批量调度。
    • Volcano调度器:使用Volcano调度器对Ray Job进行批量调度。使用Volcano作为批调度器时,若无自建Volcano,建议安装Volcano调度器插件,具体请参见Volcano调度器

    服务端口

    8080

    表示Kuberay对外提供服务的端口,默认为8080。

  5. 单击“安装”。当该插件状态为“运行中”时,则说明插件安装成功。

组件说明

表4 Kuberay组件

容器组件

说明

资源类型

kuberay-operator

进行Ray的部署和生命周期的管理。

Deployment

使用示例

本示例基于Kuberay插件,为您提供两种提交Ray作业的方式,具体工作流程和应用场景请参见表5。更多Kuberay的用法,可参考官网文档

表5 作业提交方式对比

提交方式

说明

通过Ray Cluster提交作业

您需要首先创建一个Ray Cluster,再登录该Ray Cluster的Head节点的Pod中,提交相关作业。Head节点会将作业自动分发给Worker节点,由Worker节点执行对应作业。

通过Ray Job提交作业

您可以通过Ray Job将Python脚本直接挂载至Ray Cluster的Head节点,Head节点将作业自动分发给Worker节点完成作业,本示例中的创建Ray Job的Yaml文件大致含义如下,您可以根据实际情况进行调整。

  1. Ray Job会启动一个Ray Cluster,包括Head节点和Worker节点。其中,Worker节点中Pod的数量会根据实际作业情况进行弹性伸缩。
  2. Ray Job通过ConfigMap将Python脚本挂载到Ray Cluster的Head节点中。
  3. Ray Job自动运行指定的Python脚本,执行分布式计数器任务。任务完成后,Ray Job的状态将会更新为完成。但Ray Cluster会继续保持运行,直到手动删除。
  1. 在已有的ECS中安装kubectl,并使用kubectl连接集群,具体操作请参见通过kubectl连接集群
  2. 执行以下命令,创建YAML文件my-rayjob.yaml,用于配置Ray Job,文件名称可自定义。

    vim my-rayjob.yaml

    在使用Ray官方镜像时,可能由于网络原因拉取失败。建议将该镜像提前上传至SWR镜像仓库,并将文件内容中的镜像地址替换为SWR中的镜像地址。关于镜像上传SWR镜像仓库的详细步骤,请参见使用docker命令将镜像迁移至SWR

    文件内容如下:

    apiVersion: ray.io/v1
    kind: RayJob    # 资源类型为Ray Job
    metadata:
      name: my-rayjob
    spec:           # 定义Ray Job的规格,包括任务入口点、运行时环境和Ray Cluster配置
      entrypoint: python /home/ray/samples/sample_code.py     # 指定任务的入口点命令,这里是运行一个Python脚本
      runtimeEnvYAML: |
        env_vars:   # 定义任务运行时环境变量
          counter_name: "test_counter"
      rayClusterSpec:     # 用于定义Ray Cluster配置
        headGroupSpec:    # 定义Ray Cluster的Head节点配置
          rayStartParams: {}
          template:
            spec:
              containers:
                - name: ray-head
                  image: rayproject/ray:2.41.0
                  ports:
                    - containerPort: 6379
                      name: gcs-server
                    - containerPort: 8265 # Ray dashboard
                      name: dashboard
                    - containerPort: 10001
                      name: client
                  resources:
                    limits:
                      cpu: "1"
                    requests:
                      cpu: "200m"
                  volumeMounts:
                    - mountPath: /home/ray/samples
                      name: code-sample
              volumes:
                - name: code-sample
                  configMap:
                    name: ray-job-code-sample
                    items:
                      - key: sample_code.py
                        path: sample_code.py
        workerGroupSpecs:    # 定义 Ray Cluster的Worker节点配置
          - replicas: 1
            minReplicas: 1
            maxReplicas: 5
            groupName: small-group
            rayStartParams: {}
            template:
              spec:
                containers:
                  - name: ray-worker
                    image: rayproject/ray:2.41.0
                    resources:
                      limits:
                        cpu: "1"
                      requests:
                        cpu: "200m"
    ---
    # 定义具体工作,里面包含一个Python脚本sample_code.py,该脚本实现了一个简单的分布式计数器
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ray-job-code-sample
    data:
      sample_code.py: |
        import ray
        import os
    
        ray.init()
    
        @ray.remote
        class Counter:
            def __init__(self):
                # Used to verify runtimeEnv
                self.name = os.getenv("counter_name")
                assert self.name == "test_counter"
                self.counter = 0
    
            def inc(self):
                self.counter += 1
    
            def get_counter(self):
                return "{} got {}".format(self.name, self.counter)
    
        counter = Counter.remote()
    
        for _ in range(1000):
            ray.get(counter.inc.remote())
            print(ray.get(counter.get_counter.remote()))

  3. 执行以下命令,系统将会创建Ray Job和ConfigMap(用于存放作业代码) 资源。

    kubectl create -f my-rayjob.yaml

    回显如下,表示资源创建成功。

    rayjob.ray.io/my-rayjob created
    configmap/ray-job-code-sample created

  4. 依次执行以下命令,检查Ray Job的部署情况。

    1. 执行以下命令,检查Ray Cluster是否创建成功。
      kubectl get pod

      回显结果如下,则说明创建成功。其中,“my-rayjob-raycluster-4464z-head-hb5qx”表示Head Pod,“my-rayjob-raycluster-4464z-small-group-worker-csqb2”表示Worker Pod,“my-rayjob-x2tv6”用来查看作业的执行情况。如果“my-rayjob-x2tv6”STATUS为Completed,则说明作业已完成。

      NAME                                                  READY    STATUS    RESTARTS    AGE
      my-rayjob-raycluster-4464z-head-hb5qx                 1/1      Running   0           24s
      my-rayjob-raycluster-4464z-small-group-worker-csqb2   1/1      Running   0           24s
      my-rayjob-x2tv6                                       1/1      Running   0           4s
    2. 查看Ray Job的状态。
      kubectl get rayjob

      回显结果如下,则说明作业仍在进行中。如果JOB STATUSSUCCEEDED,则说明作业已完成。

      NAME        JOB STATUS    DEPLOYMENT STATUS    RAY CLUSTER NAME              START TIME            END TIME    AGE
      my-rayjob   RUNNING       Running              my-rayjob-raycluster-4464z    2025-02-10T07:16:26Z              28
    3. 执行以下命令,查看作业的具体执行情况。
      kubectl logs my-rayjob-x2tv6

      回显结果如下:

      2025-02-21 03:32:23,631 INFO cli.py:36 -- Job submission server address: http://my-rayjob-raycluster-4464z-head-svc.default.svc.cluster.local:8265
      2025-02-21 03:32:24,142 SUCC cli.py:60 -- --------------------------------------------
      2025-02-21 03:32:24,143 SUCC cli.py:61 -- Job 'my-rayjob-x2tv6' submitted successfully
      2025-02-21 03:32:24,143 SUCC cli.py:62 -- --------------------------------------------
      2025-02-21 03:32:24,143 INFO cli.py:286 -- Next steps
      2025-02-21 03:32:24,143 INFO cli.py:287 -- Query the logs of the job:
      2025-02-21 03:32:24,143 INFO cli.py:289 -- ray job logs my-rayjob-x2tv6
      2025-02-21 03:32:24,143 INFO cli.py:291 -- Query the status of the job:
      2025-02-21 03:32:24,143 INFO cli.py:293 -- ray job status my-rayjob-x2tv6
      2025-02-21 03:32:24,143 INFO cli.py:295 -- Request the job to be stopped:
      2025-02-21 03:32:24,143 INFO cli.py:297 -- ray job stop my-rayjob-x2tv6
      2025-02-21 03:32:24,147 INFO cli.py:304 -- Tailing logs until the job exits (disable with --no-wait):
      2025-02-21 03:32:25,011 INFO worker.py:1429 -- Using address 172.20.0.10:6379 set in the environment variable RAY_ADDRESS
      2025-02-21 03:32:25,012 INFO worker.py:1564 -- Connecting to existing Ray cluster at address: 172.20.0.10:6379...
      2025-02-21 03:32:25,017 INFO worker.py:1740 -- Connected to Ray cluster. View the dashboard at 172.20.0.10:8265 
      test_counter got 1
      test_counter got 2
      test_counter got 3
      test_counter got 4
      ...

  5. 您可以在Ray Dashboard中实时监控和管理Ray Cluster的状态、资源使用情况和作业执行情况。

    1. 获取Ray Cluster中Head Pod的标签,使2中新建的Service能够识别并绑定Pod。请将“my-rayjob-raycluster-4464z-head-hb5qx”替换为您的Head Pod名称。
      kubectl describe pod my-rayjob-raycluster-4464z-head-hb5qx

      回显结果如下,建议使用“my-rayjob-raycluster-4464z-head”作为标签。

      ...
      Labels:           app.kubernetes.io/created-by=kuberay-operator
                        app.kubernetes.io/name=kuberay
                        ray.io/cluster=my-rayjob-raycluster-4464z
                        ray.io/group=headgroup
                        ray.io/identifier=my-rayjob-raycluster-4464z-head
                        ray.io/is-ray-node=yes
                        ray.io/node-type=head
      ...
    2. 执行以下命令,创建YAML文件ray-dashboard.yaml,用于配置NodePort的Service,文件名称可自定义。该Service主要用于对外暴露服务,进而可以从浏览器直接访问Ray Dashboard。
      vim ray-dashboard.yaml

      文件内容如下:

      apiVersion: v1
      kind: Service
      metadata:
        name: ray-dashboard
        labels:
          ray.io/identifier: my-rayjob-raycluster-4464z-head
        namespace: default
      spec:
        ports:
        - name: cce-service-0
          port: 8265          # 访问Service的端口,设置为8265
          protocol: TCP       # 访问Service的协议,支持TCP和UDP
          targetPort: 8265    # Service访问目标容器的端口,此端口与容器中运行的应用强相关,必须为8265
        selector:             # 标签选择器
          ray.io/identifier: my-rayjob-raycluster-4464z-head
        externalTrafficPolicy: Cluster
        type: NodePort        # Service的类型,NodePort表示在通过节点端口访问
    3. 执行以下命令,创建Service。
      kubectl create -f ray-dashboard.yaml

      回显结果如下,则说明Service创建成功。

      service/ray-dashboard created
    4. 执行以下命令,查看该Service的节点端口信息。
      kubectl get services

      回显结果如下,其中32638即为节点端口。

      NAME                                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                AGE
      ray-dashboard                         NodePort    10.247.147.102   <none>        8265:32638/TCP                         8s
    5. 在浏览器中输入“http://<集群任一节点的EIP>:32638”,访问Ray Dashboard页面。请确保集群中存在节点已绑定EIP,您可以在CCE控制台单击对应集群名称,在“节点管理 > 节点页面”,单击对应节点名称进入ECS页面绑定EIP,具体可参考绑定弹性公网IP

      如果访问界面类似图3 Ray Dashboard,则说明访问成功。您可以根据Ray Dashboard实时监控和管理Ray Cluster的状态、资源使用情况和作业执行情况。例如,您可以在Recent jobs模块查看作业执行状况。

      图2 Ray Dashboard

  6. 依次执行以下步骤,删除相关资源。

    1. 删除Ray Job相关资源。
      kubectl delete -f my-rayjob.yaml

      回显结果如下:

      rayjob.ray.io "my-rayjob" deleted
      configmap "ray-job-code-sample" deleted
    2. 删除Service资源。
      kubectl delete -f ray-dashboard.yaml

      回显结果如下:

      service "ray-dashboard" deleted

常见问题

在CCE中卸载Kuberay插件时,Ray Cluster、Ray Job和Ray Service的CRD会残留在集群中。您可以参考以下步骤进行处理:

  1. 在已连接集群的ECS中,执行以下命令,查找与Ray相关的CRD。

    kubectl get crd | grep ray

    回显结果如下,则说明存在两个相关的CRD。

    rayclusters.ray.io                          2025-02-01T12:00:00Z 
    rayjobs.ray.io                              2025-02-01T12:00:00Z
    rayservices.ray.io                          2025-02-01T12:00:00Z

  2. 执行以下命令,依次删除相关资源。命令中的“rayclusters.ray.io”、“rayjobs.ray.io”和“rayservices.ray.io”可替换为您残留的CRD名称。

    kubectl delete crd rayclusters.ray.io
    kubectl delete crd rayjobs.ray.io
    kubectl delete crd rayservices.ray.io

    回显结果如下,则说明资源已删除。

    customresourcedefinition.apiextensions.k8s.io "rayclusters.ray.io" deleted
    customresourcedefinition.apiextensions.k8s.io "rayjobs.ray.io" deleted
    customresourcedefinition.apiextensions.k8s.io "rayservices.ray.io" deleted

版本记录

表6 KubeRay插件版本记录

插件版本

支持的集群版本

更新特性

社区版本

1.2.3

  • v1.27
  • v1.28
  • v1.29
  • v1.30
  • v1.31
  • v1.32

支持1.32版本集群

v1.2.2

1.2.2

  • v1.27
  • v1.28
  • v1.29
  • v1.30
  • v1.31

新增Kuberay插件

v1.2.2