在 GKE 中配置 KubeRay 以使用 Google Cloud Storage 存储桶#

如果您已熟悉 GKE 中的工作负载身份,则可以跳过本文档。关键在于,在将 Kubernetes 服务帐户链接到 Google Cloud 服务帐户后,您需要在每个 Ray Pod 中指定一个服务帐户。否则,请继续阅读。

本示例是 https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity 上文档的缩减版。如果您对详细信息感兴趣,值得阅读完整文档。

在 GKE 中创建 Kubernetes 集群#

本示例使用 GKE 创建了一个最小化的 KubeRay 集群。

在本地机器或 Google Cloud Shell 上运行此命令及所有后续命令。如果从本地机器运行,请安装 Google Cloud SDK

PROJECT_ID=my-project-id # Replace my-project-id with your GCP project ID
CLUSTER_NAME=cloud-bucket-cluster
ZONE=us-west1-b

gcloud container clusters create $CLUSTER_NAME \
    --addons=RayOperator \
    --num-nodes=1 --min-nodes 0 --max-nodes 1 --enable-autoscaling \
    --zone=$ZONE --machine-type e2-standard-8 \
    --workload-pool=${PROJECT_ID}.svc.id.goog 

此命令将在 us-west1-b 区域创建一个名为 cloud-bucket-cluster 的 Kubernetes 集群,其中包含一个节点。本示例使用了 e2-standard-8 机器类型,该类型具有 8 个 vCPU 和 32 GB RAM。

有关如何查找项目 ID 的更多信息,请参阅 https://support.google.com/googleapi/answer/7014113?hl=enhttps://cloud.google.com/resource-manager/docs/creating-managing-projects

现在获取集群的凭据以供 kubectl 使用

gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID

创建 Kubernetes 服务帐户#

NAMESPACE=default
KSA=my-ksa
kubectl create serviceaccount $KSA -n $NAMESPACE

配置 GCS 存储桶#

创建一个 Ray 用作远程文件系统的 GCS 存储桶。

BUCKET=my-bucket
gcloud storage buckets create gs://$BUCKET --uniform-bucket-level-access

roles/storage.objectUser 角色绑定到 Kubernetes 服务帐户和存储桶 IAM 策略。请参阅 识别项目 以查找您的项目 ID 和项目编号。

PROJECT_ID=<your project ID>
PROJECT_NUMBER=<your project number>
gcloud storage buckets add-iam-policy-binding gs://${BUCKET} --member "principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/${NAMESPACE}/sa/${KSA}"  --role "roles/storage.objectUser"

有关更多详细信息,请参阅 从 GKE 工作负载访问 Google Cloud API

创建最小化的 RayCluster YAML 清单#

您可以使用 curl 下载本教程的 RayCluster YAML 清单,如下所示:

curl -LO https://raw.githubusercontent.com/ray-project/kuberay/v1.5.1/ray-operator/config/samples/ray-cluster.gke-bucket.yaml

关键部分是以下几行:

      spec:
        serviceAccountName: my-ksa
        nodeSelector:
          iam.gke.io/gke-metadata-server-enabled: "true"

在 Ray 集群的每个 Pod 规范中包含这些行。本示例为简单起见,使用了单节点集群(1 个头节点和 0 个工作节点)。

创建 RayCluster#

kubectl apply -f ray-cluster.gke-bucket.yaml

从 RayCluster 测试 GCS 存储桶访问#

使用 kubectl get pod 获取 Ray 头 Pod 的名称。然后运行以下命令在 Ray 头 Pod 中获取 shell:

kubectl exec -it raycluster-mini-head-xxxx -- /bin/bash

在 shell 中,运行 pip install google-cloud-storage 来安装 Google Cloud Storage Python 客户端库。

(对于生产用例,您需要确保 google-cloud-storage 已安装在集群的每个节点上,或使用 ray.init(runtime_env={"pip": ["google-cloud-storage"]}) 在运行时按需安装包——有关更多详细信息,请参阅 https://docs.rayai.org.cn/en/latest/ray-core/handling-dependencies.html#runtime-environments)。

然后运行以下 Python 代码来测试对存储桶的访问:

import ray
import os
from google.cloud import storage

GCP_GCS_BUCKET = "my-bucket"
GCP_GCS_FILE = "test_file.txt"

ray.init(address="auto")

@ray.remote
def check_gcs_read_write():
    client = storage.Client()
    bucket = client.bucket(GCP_GCS_BUCKET)
    blob = bucket.blob(GCP_GCS_FILE)

    # Write to the bucket
    blob.upload_from_string("Hello, Ray on GKE!")

    # Read from the bucket
    content = blob.download_as_text()

    return content

result = ray.get(check_gcs_read_write.remote())
print(result)

您应该会看到以下输出:

Hello, Ray on GKE!