使用 ArgoCD 部署 Ray 集群#

本指南提供了使用 ArgoCD 在 Kubernetes 上部署 Ray 集群的分步方法。ArgoCD 是一个声明式的 GitOps 工具,它使您能够通过自动化同步、版本控制和回滚功能来管理 Git 存储库中的 Ray 集群配置。当跨不同环境管理多个 Ray 集群、实施审计跟踪和审批工作流或维护基础架构即代码实践时,此方法特别有价值。对于单集群开发或快速实验等更简单的用例,直接使用 kubectl 或 Helm 部署可能已足够。您可以在 此处 阅读有关 ArgoCD 优势的更多信息。

本示例演示了如何利用 ArgoCD 的 GitOps 功能自动管理集群,来部署 KubeRay Operator 和一个带有三个不同工作节点组的 RayCluster。

先决条件#

在继续本指南之前,请确保您拥有以下条件

  • 具有运行 Ray 工作负载所需资源的 Kubernetes 集群。

  • 已配置 kubectl 以访问您的 Kubernetes 集群。

  • (可选)在您的 Kubernetes 集群上已安装 ArgoCD

  • (可选)在本地计算机上已安装 ArgoCD CLI(推荐,便于管理应用程序。根据您的环境,可能需要端口转发和登录)。

  • (可选)可以访问 ArgoCD UI 或 API 服务器。

步骤 1:部署 KubeRay Operator CRD#

首先,部署 KubeRay Operator 所需的自定义资源定义 (CRD)。创建一个名为 ray-operator-crds.yaml 的文件,内容如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ray-operator-crds
  namespace: argocd
spec:
  project: default
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  source:
    repoURL: https://github.com/ray-project/kuberay
    targetRevision: v1.5.1  # update this as necessary
    path: helm-chart/kuberay-operator/crds
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - Replace=true

应用 ArgoCD 应用程序

kubectl apply -f ray-operator-crds.yaml

等待 CRD 应用程序同步并变为健康状态。您可以使用以下命令检查状态:

kubectl get application ray-operator-crds -n argocd

最终应显示类似如下内容:

NAME                SYNC STATUS   HEALTH STATUS
ray-operator-crds   Synced        Healthy

或者,如果您已安装 ArgoCD CLI,则可以等待应用程序

argocd app wait ray-operator-crds

步骤 2:部署 KubeRay Operator#

在安装完 CRD 后,部署 KubeRay Operator 本身。创建一个名为 ray-operator.yaml 的文件,内容如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ray-operator
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/ray-project/kuberay
    targetRevision: v1.5.1  # update this as necessary
    path: helm-chart/kuberay-operator
    helm:
      skipCrds: true   # CRDs are already installed in Step 1
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

请注意 Helm 配置中的 skipCrds: true 设置。这是必需的,因为 CRD 已在步骤 1 中单独安装。

应用 ArgoCD 应用程序

kubectl apply -f ray-operator.yaml

等待 Operator 应用程序同步并变为健康状态。您可以使用以下命令检查状态:

kubectl get application ray-operator -n argocd

最终应显示以下输出:

NAME           SYNC STATUS   HEALTH STATUS
ray-operator   Synced        Healthy

或者,如果您已安装 ArgoCD CLI

argocd app wait ray-operator

验证 KubeRay Operator Pod 是否正在运行

kubectl get pods -n ray-cluster -l app.kubernetes.io/name=kuberay-operator

步骤 3:部署 RayCluster#

现在,部署一个启用了自动伸缩功能且具有三个不同工作节点组的 RayCluster。创建一个名为 raycluster.yaml 的文件,内容如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: raycluster
  namespace: argocd
spec:
  project: default
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  ignoreDifferences:
    - group: ray.io
      kind: RayCluster
      name: raycluster-kuberay
      namespace: ray-cluster
      jqPathExpressions:
        - .spec.workerGroupSpecs[].replicas
  source:
    repoURL: https://ray-project.github.io/kuberay-helm/
    chart: ray-cluster
    targetRevision: "1.5.1"
    helm:
      releaseName: raycluster
      valuesObject:
        image:
          repository: docker.io/rayproject/ray
          tag: latest
          pullPolicy: IfNotPresent
        head:
          rayStartParams:
            num-cpus: "0"
          enableInTreeAutoscaling: true
          autoscalerOptions:
            version: v2
            upscalingMode: Default
            idleTimeoutSeconds: 600 # 10 minutes
            env:
            - name: AUTOSCALER_MAX_CONCURRENT_LAUNCHES
              value: "100"
        worker:
          groupName: standard-worker
          replicas: 1
          minReplicas: 1
          maxReplicas: 200
          rayStartParams:
            resources: '"{\"standard-worker\": 1}"'
          resources:
            requests:
              cpu: "1"
              memory: "1G"
        additionalWorkerGroups:
          additional-worker-group1:
            image:
              repository: docker.io/rayproject/ray
              tag: latest
              pullPolicy: IfNotPresent
            disabled: false
            replicas: 1
            minReplicas: 1
            maxReplicas: 30
            rayStartParams:
              resources: '"{\"additional-worker-group1\": 1}"'
            resources:
              requests:
                cpu: "1"
                memory: "1G"
          additional-worker-group2:
            image:
              repository: docker.io/rayproject/ray
              tag: latest
              pullPolicy: IfNotPresent
            disabled: false
            replicas: 1
            minReplicas: 1
            maxReplicas: 200
            rayStartParams:
              resources: '"{\"additional-worker-group2\": 1}"'
            resources:
              requests:
                cpu: "1"
                memory: "1G"
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

应用 ArgoCD 应用程序

kubectl apply -f raycluster.yaml

等待 RayCluster 应用程序同步并变为健康状态。您可以使用以下命令检查状态:

kubectl get application raycluster -n argocd

或者,如果您已安装 ArgoCD CLI

argocd app wait raycluster

验证 RayCluster 是否正在运行

kubectl get raycluster -n ray-cluster

这将显示类似如下内容:

NAME                 DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
raycluster-kuberay   3                 3                   ...    ...      ...    ready    ...

您应该会看到 head Pod 和 worker Pod

kubectl get pods -n ray-cluster

显示类似如下内容:

NAME                                               READY   STATUS    RESTARTS   AGE
kuberay-operator-6c485bc876-28dnl                  1/1     Running   0          11d
raycluster-kuberay-additional-worker-group1-n45rc   1/1     Running   0          5d21h
raycluster-kuberay-additional-worker-group2-b2455   1/1     Running   0          2d18h
raycluster-kuberay-head                            2/2     Running   0          5d21h
raycluster-kuberay-standard-worker-worker-bs8t8    1/1     Running   0          5d21h

理解 ArgoCD 中的 Ray 自动伸缩#

确定要忽略的字段#

RayCluster 应用程序配置中的 ignoreDifferences 部分对于正确的自动伸缩至关重要。要确定需要忽略哪些字段,您可以检查 RayCluster 资源以识别在运行时动态更改的字段。

首先,描述 RayCluster 资源以查看其完整的规范

kubectl describe raycluster raycluster-kuberay -n ray-cluster

或者,以 YAML 格式获取资源,以查看确切的字段路径

kubectl get raycluster raycluster-kuberay -n ray-cluster -o yaml

查找被控制器或自动伸缩器修改的字段。对于 Ray,自动伸缩器会修改每个工作节点组规范下的 replicas 字段。您将看到类似以下的输出:

spec:
  workerGroupSpecs:
  - replicas: 5  # This value changes dynamically
    minReplicas: 1
    maxReplicas: 200
    groupName: standard-worker
    # ...

当 ArgoCD 检测到所需状态(在 Git 中)与实际状态(在集群中)之间的差异时,它将在 UI 或通过 CLI 中显示这些差异。

argocd app diff raycluster

如果您看到控制器(如自动伸缩器)管理的字段重复出现差异,则这些字段是 ignoreDifferences 的候选。

配置 ignoreDifferences#

RayCluster 应用程序配置中的 ignoreDifferences 部分会告知 ArgoCD 要忽略哪些字段。如果没有此设置,ArgoCD 和 Ray 自动伸缩器可能会发生冲突,导致在动态请求工作节点时出现意外行为(例如,使用 ray.autoscaler.sdk.request_resources)。具体来说,当请求 N 个工作节点时,自动伸缩器可能不会启动预期数量的工作节点,因为 ArgoCD 可能会将副本计数恢复到应用程序清单中定义的原始值。

推荐的方法是使用 jqPathExpressions,它会自动处理任意数量的工作节点组。

ignoreDifferences:
  - group: ray.io
    kind: RayCluster
    name: raycluster-kuberay
    namespace: ray-cluster
    jqPathExpressions:
      - .spec.workerGroupSpecs[].replicas

此配置告诉 ArgoCD 忽略所有工作节点组的 replicas 字段的差异。 jqPathExpressions 字段使用带有数组通配符([])的 JQ 语法,这意味着在添加或删除工作节点组时,您无需更新配置。

注意namenamespace 必须与您的 RayCluster 资源名称和命名空间匹配。如果您已自定义这些值,请单独验证。

备选方案:使用 jsonPointers

如果您偏好显式配置,则可以使用 jsonPointers 替代

ignoreDifferences:
  - group: ray.io
    kind: RayCluster
    name: raycluster-kuberay
    namespace: ray-cluster
    jsonPointers:
      - /spec/workerGroupSpecs/0/replicas
      - /spec/workerGroupSpecs/1/replicas
      - /spec/workerGroupSpecs/2/replicas

使用 jsonPointers 时,您必须按索引明确列出每个工作节点组:

  • /spec/workerGroupSpecs/0/replicas - 第一个工作节点组(默认的 worker 组)

  • /spec/workerGroupSpecs/1/replicas - 第二个工作节点组(additional-worker-group1

  • /spec/workerGroupSpecs/2/replicas - 第三个工作节点组(additional-worker-group2

如果您添加或删除工作节点组,则 **必须** 相应地更新此列表。索引对应于 RayCluster 规范中工作节点组的出现顺序,默认的 worker 组位于索引 0,additionalWorkerGroups 则按其定义顺序排列。

有关这两种方法的更多详细信息,请参阅 ArgoCD diff 自定义文档

通过忽略这些差异,ArgoCD 允许 Ray 自动伸缩器在不受干扰的情况下动态管理工作节点副本。

步骤 4:访问 Ray Dashboard#

要访问 Ray Dashboard,请端口转发 head 服务

kubectl port-forward -n ray-cluster svc/raycluster-kuberay-head-svc 8265:8265

在浏览器中导航到 https://:8265 以查看 Ray Dashboard。

自定义配置#

您可以通过修改 raycluster.yaml 文件中的 valuesObject 部分来自定义 RayCluster 配置:

  • 镜像:更改 repositorytag 以使用不同的 Ray 版本。

  • 工作节点组:通过修改 additionalWorkerGroups 部分来添加或删除工作节点组。

  • 自动伸缩:调整 minReplicasmaxReplicasidleTimeoutSeconds 以控制自动伸缩行为。

  • 资源:修改 rayStartParams 为工作节点组分配自定义资源。

进行更改后,将它们提交到您的 Git 存储库。如果启用了自动同步,ArgoCD 将自动将更改同步到您的集群。

备选方案:将所有内容部署到一个文件中#

如果您希望一次性部署所有组件,可以将所有三个 ArgoCD 应用程序合并到一个文件中。创建一个名为 ray-argocd-all.yaml 的文件,内容如下:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ray-operator-crds
  namespace: argocd
spec:
  project: default
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  source:
    repoURL: https://github.com/ray-project/kuberay
    targetRevision: v1.5.1  # update this as necessary
    path: helm-chart/kuberay-operator/crds
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - Replace=true

---

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ray-operator
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/ray-project/kuberay
    targetRevision: v1.5.1  # update this as necessary
    path: helm-chart/kuberay-operator
    helm:
      skipCrds: true   # CRDs are installed in the first Application
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

---

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: raycluster
  namespace: argocd
spec:
  project: default
  destination:
    server: https://kubernetes.default.svc
    namespace: ray-cluster
  ignoreDifferences:
    - group: ray.io
      kind: RayCluster
      name: raycluster-kuberay # ensure this is aligned with the release name
      namespace: ray-cluster   # ensure this is aligned with the namespace
      jqPathExpressions:
        - .spec.workerGroupSpecs[].replicas
  source:
    repoURL: https://ray-project.github.io/kuberay-helm/
    chart: ray-cluster
    targetRevision: "1.4.1"
    helm:
      releaseName: raycluster  # this affects the ignoreDifferences field
      valuesObject:
        image:
          repository: docker.io/rayproject/ray
          tag: latest
          pullPolicy: IfNotPresent
        head:
          rayStartParams:
            num-cpus: "0"
          enableInTreeAutoscaling: true
          autoscalerOptions:
            version: v2
            upscalingMode: Default
            idleTimeoutSeconds: 600 # 10 minutes
            env:
            - name: AUTOSCALER_MAX_CONCURRENT_LAUNCHES
              value: "100"
        worker:
          groupName: standard-worker
          replicas: 1
          minReplicas: 1
          maxReplicas: 200
          rayStartParams:
            resources: '"{\"standard-worker\": 1}"'
          resources:
            requests:
              cpu: "1"
              memory: "1G"
        additionalWorkerGroups:
          additional-worker-group1:
            image:
              repository: docker.io/rayproject/ray
              tag: latest
              pullPolicy: IfNotPresent
            disabled: false
            replicas: 1
            minReplicas: 1
            maxReplicas: 30
            rayStartParams:
              resources: '"{\"additional-worker-group1\": 1}"'
            resources:
              requests:
                cpu: "1"
                memory: "1G"
          additional-worker-group2:
            image:
              repository: docker.io/rayproject/ray
              tag: latest
              pullPolicy: IfNotPresent
            disabled: false
            replicas: 1
            minReplicas: 1
            maxReplicas: 200
            rayStartParams:
              resources: '"{\"additional-worker-group2\": 1}"'
            resources:
              requests:
                cpu: "1"
                memory: "1G"
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

在此示例中,请注意使用了 jqPathExpressions 方法。

一次应用所有三个应用程序

kubectl apply -f ray-argocd-all.yaml

这种单文件方法对于快速部署很方便,但前面各节中的分步方法可以更好地了解部署过程,并且更容易排除故障。