Ray Serve-Anwendung mit einem Stable Diffusion-Modell in Google Kubernetes Engine (GKE) bereitstellen


Dieser Leitfaden enthält ein Beispiel für die Bereitstellung eines Stable Diffusion-Modells in Google Kubernetes Engine (GKE) mithilfe von Ray-Serve und dem Ray Operator-Add-on als Beispielimplementierung.

Ray und Ray Serve

Ray ist ein skalierbares Open-Source-Computing-Framework für KI/ML-Anwendungen. Ray Serve ist eine Modellbereitstellungsbibliothek für Ray, die zur Skalierung und Bereitstellung von Modellen in einer verteilten Umgebung verwendet wird. Weitere Informationen finden Sie unter Ray Serve in der Ray-Dokumentation.

Sie können eine RayCluster- oder RayService-Ressource verwenden, um Ihre Ray Serve-Anwendungen bereitzustellen. Sie sollten eine RayService-Ressource aus folgenden Gründen in der Produktion verwenden:

  • Direkte Updates für RayService-Anwendungen
  • Upgrades ohne Ausfallzeiten für RayCluster-Ressourcen
  • Hochverfügbare Ray Serve-Anwendungen

Ziele

Dieser Leitfaden richtet sich an Kunden von generativer KI, neue oder bestehende Nutzer von GKE, ML-Entwickler, MLOps-Entwickler (DevOps) oder Plattformadministratoren, die daran interessiert sind, Funktionen zur Kubernetes-Containerorchestrierung für die Bereitstellung von Modellen mit Ray zu nutzen.

  • GKE-Cluster mit einem GPU-Knotenpool erstellen
  • Ray-Cluster mithilfe der benutzerdefinierten RayCluster erstellen
  • Ray Serve-Anwendung ausführen
  • Benutzerdefinierte RayService bereitstellen

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweise

Die Software, die Sie für diese Anleitung benötigen, ist in Cloud Shell vorinstalliert, einschließlich kubectl und der gcloud CLI. Wenn Sie Cloud Shell nicht verwenden, müssen Sie die gcloud CLI installieren.

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.
  3. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the GKE API:

    gcloud services enable container.googleapis.com
  7. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/container.clusterAdmin, roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.
  8. Installieren Sie RayServe

Umgebung vorbereiten

So richten Sie Ihre Umgebung ein:

  1. Starten Sie eine Cloud Shell-Sitzung über die Google Cloud Console. Klicken Sie dazu in der Google Cloud Console auf Symbol für die Cloud Shell-Aktivierung Cloud Shell aktivieren. Dadurch wird im unteren Bereich der Google Cloud Console eine Sitzung gestartet.

  2. Legen Sie Umgebungsvariablen fest:

    export PROJECT_ID=PROJECT_ID
    export CLUSTER_NAME=rayserve-cluster
    export COMPUTE_REGION=us-central1
    export COMPUTE_ZONE=us-central1-c
    export CLUSTER_VERSION=CLUSTER_VERSION
    export TUTORIAL_HOME=`pwd`
    

    Ersetzen Sie Folgendes:

    • PROJECT_ID: Ihre Google Cloud-Projekt-ID.
    • CLUSTER_VERSION ist die zu verwendende GKE-Version. Es muss 1.30.1 oder höher sein.
  3. Klonen Sie das GitHub-Repository:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. Wechseln Sie in das Arbeitsverzeichnis:

    cd kubernetes-engine-samples/ai-ml/gke-ray/rayserve/stable-diffusion
    

Cluster mit einem GPU-Knotenpool erstellen

Erstellen Sie einen Autopilot- oder Standard-GKE-Cluster mit einem GPU-Knotenpool:

Autopilot-Cluster erstellen:

gcloud container clusters create-auto ${CLUSTER_NAME}  \
    --enable-ray-operator \
    --cluster-version=${CLUSTER_VERSION} \
    --location=${COMPUTE_REGION}

Standardcluster erstellen:

gcloud container clusters create ${CLUSTER_NAME} \
    --addons=RayOperator \
    --cluster-version=${CLUSTER_VERSION}  \
    --machine-type=g2-standard-8 \
    --location=${COMPUTE_ZONE} \
    --num-nodes=2 \
    --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest

RayCluster-Ressource bereitstellen

So stellen Sie eine RayCluster-Ressource bereit:

  1. Prüfen Sie das folgende Manifest:

    apiVersion: ray.io/v1
    kind: RayCluster
    metadata:
      name: stable-diffusion-cluster
    spec:
      rayVersion: '2.9.0'
      headGroupSpec:
        rayStartParams:
          dashboard-host: '0.0.0.0'
        template:
          metadata:
          spec:
            containers:
            - name: ray-head
              image: rayproject/ray-ml:2.9.0
              ports:
              - containerPort: 6379
                name: gcs
              - containerPort: 8265
                name: dashboard
              - containerPort: 10001
                name: client
              - containerPort: 8000
                name: serve
              resources:
                limits:
                  cpu: "2"
                  memory: "8Gi"
                requests:
                  cpu: "2"
                  memory: "8Gi"
      workerGroupSpecs:
      - replicas: 1
        minReplicas: 1
        maxReplicas: 4
        groupName: gpu-group
        rayStartParams: {}
        template:
          spec:
            containers:
            - name: ray-worker
              image: rayproject/ray-ml:2.9.0
              resources:
                limits:
                  cpu: 4
                  memory: "16Gi"
                  nvidia.com/gpu: 1
                requests:
                  cpu: 3
                  memory: "16Gi"
                  nvidia.com/gpu: 1
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-l4

    Dieses Manifest beschreibt eine RayCluster-Ressource.

  2. Wenden Sie das Manifest auf Ihren Cluster an:

    kubectl apply -f ray-cluster.yaml
    
  3. Prüfen Sie, ob die RayCluster-Ressource bereit ist:

    kubectl get raycluster
    

    Die Ausgabe sieht in etwa so aus:

    NAME                       DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
    stable-diffusion-cluster   2                 2                   6      20Gi     0      ready    33s
    

    In dieser Ausgabe gibt ready in der Spalte STATUS an, dass die RayCluster-Ressource bereit ist.

Verbindung zur RayCluster-Ressource herstellen

So stellen Sie eine Verbindung zur RayCluster-Ressource her:

  1. Prüfen Sie, ob GKE den RayCluster-Dienst erstellt hat:

    kubectl get svc stable-diffusion-cluster-head-svc
    

    Die Ausgabe sieht in etwa so aus:

    NAME                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                AGE
    pytorch-mnist-cluster-head-svc   ClusterIP   34.118.238.247   <none>        10001/TCP,8265/TCP,6379/TCP,8080/TCP   109s
    
  2. Richten Sie Portweiterleitungssitzungen für den Ray-Head ein:

    kubectl port-forward svc/stable-diffusion-cluster-head-svc 8265:8265 2>&1 >/dev/null &
    kubectl port-forward svc/stable-diffusion-cluster-head-svc 10001:10001 2>&1 >/dev/null &
    
  3. Prüfen Sie, ob der Ray-Client mithilfe von localhost eine Verbindung zum Ray-Cluster herstellen kann:

    ray list nodes --address http://localhost:8265
    

    Die Ausgabe sieht in etwa so aus:

    ======== List: 2024-06-19 15:15:15.707336 ========
    Stats:
    ------------------------------
    Total: 3
    
    Table:
    ------------------------------
        NODE_ID                                                   NODE_IP     IS_HEAD_NODE    STATE    NODE_NAME    RESOURCES_TOTAL                 LABELS
    0  1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2  10.28.1.21  False           ALIVE    10.28.1.21   CPU: 2.0                        ray.io/node_id: 1d07447d7d124db641052a3443ed882f913510dbe866719ac36667d2
    # Several lines of output omitted
    

Ray Serve-Anwendung ausführen

So führen Sie eine Ray Serve-Anwendung aus:

  1. Führen Sie die Anwendung "Stable Diffusion Ray Serve" aus:

    serve run stable_diffusion:entrypoint --working-dir=. --runtime-env-json='{"pip": ["torch", "torchvision", "diffusers==0.12.1"]}' --address ray://localhost:10001
    

    Die Ausgabe sieht in etwa so aus:

    2024-06-19 18:20:58,444 INFO scripts.py:499 -- Running import path: 'stable_diffusion:entrypoint'.
    2024-06-19 18:20:59,730 INFO packaging.py:530 -- Creating a file package for local directory '.'.
    2024-06-19 18:21:04,833 INFO handle.py:126 -- Created DeploymentHandle 'hyil6u9f' for Deployment(name='StableDiffusionV2', app='default').
    2024-06-19 18:21:04,834 INFO handle.py:126 -- Created DeploymentHandle 'xo25rl4k' for Deployment(name='StableDiffusionV2', app='default').
    2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle '57x9u4fp' for Deployment(name='APIIngress', app='default').
    2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle 'xr6kt85t' for Deployment(name='StableDiffusionV2', app='default').
    2024-06-19 18:21:04,836 INFO handle.py:126 -- Created DeploymentHandle 'g54qagbz' for Deployment(name='APIIngress', app='default').
    2024-06-19 18:21:19,139 INFO handle.py:126 -- Created DeploymentHandle 'iwuz00mv' for Deployment(name='APIIngress', app='default').
    2024-06-19 18:21:19,139 INFO api.py:583 -- Deployed app 'default' successfully.
    
  2. Richten Sie eine Portweiterleitungssitzung zum Ray Serve-Port (8000) ein:

    kubectl port-forward svc/stable-diffusion-cluster-head-svc 8000:8000 2>&1 >/dev/null &
    
  3. Führen Sie das Python-Skript aus:

    python generate_image.py
    

    Das Skript generiert ein Image in einer Datei mit dem Namen output.png. Das Bild sieht in etwa so aus:

    Ein Strand bei Sonnenuntergang. Durch Stable Diffusion generiertes Bild.

RayService bereitstellen

Die benutzerdefinierte RayService verwaltet den Lebenszyklus einer RayCluster-Ressource und Ray Serve-Anwendung.

Weitere Informationen zu RayService finden Sie unter Ray-Serve-Anwendungen bereitstellen und Produktionsanleitung in der Ray-Dokumentation.

So stellen Sie eine RayService-Ressource bereit:

  1. Prüfen Sie das folgende Manifest:

    apiVersion: ray.io/v1
    kind: RayService
    metadata:
      name: stable-diffusion
    spec:
      serveConfigV2: |
        applications:
          - name: stable_diffusion
            import_path: ai-ml.gke-ray.rayserve.stable-diffusion.stable_diffusion:entrypoint
            runtime_env:
              working_dir: "https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/archive/main.zip"
              pip: ["diffusers==0.12.1"]
      rayClusterConfig:
        rayVersion: '2.9.0'
        headGroupSpec:
          rayStartParams:
            dashboard-host: '0.0.0.0'
          template:
            spec:
              containers:
              - name: ray-head
                image: rayproject/ray-ml:2.9.0
                ports:
                - containerPort: 6379
                  name: gcs
                - containerPort: 8265
                  name: dashboard
                - containerPort: 10001
                  name: client
                - containerPort: 8000
                  name: serve
                resources:
                  limits:
                    cpu: "2"
                    memory: "8Gi"
                  requests:
                    cpu: "2"
                    memory: "8Gi"
        workerGroupSpecs:
        - replicas: 1
          minReplicas: 1
          maxReplicas: 4
          groupName: gpu-group
          rayStartParams: {}
          template:
            spec:
              containers:
              - name: ray-worker
                image: rayproject/ray-ml:2.9.0
                resources:
                  limits:
                    cpu: 4
                    memory: "16Gi"
                    nvidia.com/gpu: 1
                  requests:
                    cpu: 3
                    memory: "16Gi"
                    nvidia.com/gpu: 1
              nodeSelector:
                cloud.google.com/gke-accelerator: nvidia-l4

    Dieses Manifest beschreibt eine benutzerdefinierte RayService-Ressource.

  2. Wenden Sie das Manifest auf Ihren Cluster an:

    kubectl apply -f ray-service.yaml
    
  3. Prüfen Sie, ob der Dienst bereit ist:

    kubectl get svc stable-diffusion-serve-svc
    

    Die Ausgabe sieht in etwa so aus:

    NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE 
    
    stable-diffusion-serve-svc   ClusterIP   34.118.236.0   <none>        8000/TCP   31m 
    
  4. Konfigurieren Sie die Portweiterleitung an den Ray Serve Service:

    kubectl port-forward stable-diffusion-serve-svc 8000:8000 
    
  5. Führen Sie das Python-Skript aus dem vorherigen Abschnitt aus:

    python generate_image.py
    

    Das Skript generiert ein Bild, das dem im vorherigen Abschnitt generierten Bild ähnelt.

Bereinigen

Projekt löschen

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

Einzelne Ressourcen löschen

Zum Löschen des Clusters geben Sie Folgendes ein:

gcloud container clusters delete ${CLUSTER_NAME}

Nächste Schritte

  • Referenzarchitekturen, Diagramme und Best Practices zu Google Cloud kennenlernen. Weitere Informationen zu Cloud Architecture Center