Mit KEDA auf null skalieren

In dieser Anleitung wird gezeigt, wie Sie Ihre GKE-Arbeitslasten mit KEDA auf null Pods skalieren. Wenn Sie die Bereitstellungen auf null Pods skalieren, sparen Sie Ressourcen in Zeiten der Inaktivität (z. B. an Wochenenden und außerhalb der Bürozeiten) oder für intermittierende Arbeitslasten wie periodische Jobs.

Ziele

In dieser Anleitung werden die folgenden Anwendungsfälle beschrieben:

  • Pub/Sub-Arbeitslast auf null skalieren: Die Anzahl der Pods wird proportional zur Anzahl der Nachrichten skaliert, die im Pub/Sub-Thema in der Warteschlange stehen. Wenn die Warteschlange leer ist, wird die Arbeitslast automatisch auf null Pods herunterskaliert.
  • LLM-Arbeitslast auf null skalieren Stellen Sie Ihre LLM-Modellserver auf Knoten mit GPU bereit. Wenn der Dienst inaktiv ist, wird die Arbeitslast automatisch auf null Pods herunterskaliert.

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 Nutzern von Google Cloud steht möglicherweise ein kostenloser Testzeitraum 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

In dieser Anleitung verwenden Sie Cloud Shell zum Ausführen von Befehlen. Cloud Shell ist eine Shell-Umgebung für die Verwaltung von Ressourcen, die in Google Cloudgehostet werden. Es ist bei Google Cloud CLI, kubectl, Helm und Terraform-Befehlszeilentools vorinstalliert. Wenn Sie Cloud Shell nicht verwenden, müssen Sie die Google Cloud CLI und Helm installieren.

  1. Richten Sie die gcloud CLI in einer der folgenden Entwicklungsumgebungen ein, um die Befehle auf dieser Seite auszuführen:

    Cloud Shell

    Wenn Sie ein Onlineterminal mit bereits eingerichteter gcloud CLI verwenden möchten, aktivieren Sie Cloud Shell:

    Unten auf dieser Seite wird eine Cloud Shell-Sitzung gestartet und eine Eingabeaufforderung angezeigt. Das Initialisieren der Sitzung kann einige Sekunden dauern.

    Lokale Shell

    So verwenden Sie eine lokale Entwicklungsumgebung:

    1. Installieren Sie die gcloud CLI.
    2. Initialisieren Sie die gcloud CLI.
    3. Helm installieren, ein Kubernetes-Paketverwaltungstool
  2. 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.
  3. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  7. Verify that billing is enabled for your Google Cloud project.

  8. Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  9. Umgebung einrichten

    So richten Sie Ihre Umgebung mit Cloud Shell ein:

    1. Legen Sie Umgebungsvariablen fest:

      export PROJECT_ID=PROJECT_ID
      export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
      export LOCATION=LOCATION
      

      Ersetzen Sie PROJECT_ID durch Ihre Google Cloud Projekt-ID und LOCATION durch die Regionen oder Zonen, in denen Ihr GKE-Cluster erstellt werden soll.

      Wenn Sie die gesamte Anleitung nicht in einer einzigen Sitzung durchgehen oder Ihre Umgebungsvariablen aus irgendeinem Grund nicht festgelegt sind, müssen Sie diesen Befehl noch einmal ausführen, um die Variablen wieder festzulegen.

    2. Erstellen Sie einen GKE Standard-Cluster mit aktivierter automatischen Clusterskalierung und Identitätsföderation von Arbeitslasten für GKE:

      gcloud container clusters create scale-to-zero \
          --project=${PROJECT_ID} --location=${LOCATION} \
          --machine-type=n1-standard-2 \
          --enable-autoscaling --min-nodes=1 --max-nodes=5 \
          --workload-pool=${PROJECT_ID}.svc.id.goog
      

    KEDA installieren

    KEDA ist eine Komponente, die das horizontale Pod-Autoscaling von Kubernetes ergänzt. Mit KEDA können Sie ein Deployment auf null Pods und von null Pods auf einen Pod skalieren. Ein Deployment ist ein Kubernetes-API-Objekt, mit dem Sie mehrere Replikate von Pods ausführen können, die auf die Knoten in einem Cluster verteilt sind. Der standardmäßige Algorithmus für horizontales Pod-Autoscaling wird angewendet, nachdem GKE mindestens einen Pod erstellt hat.

    Nachdem GKE das Deployment auf null Pods skaliert hat, kann das Autoscaling nicht auf Pod-Messwerte wie die CPU-Auslastung zurückgreifen, da keine Pods ausgeführt werden. Daher können mit KEDA Messwerte, die von außerhalb des Clusters stammen, über eine Implementierung der Kubernetes External Metrics API abgerufen werden. Mit dieser API können Sie das automatische Skalieren basierend auf Messwerten wie der Anzahl der ausstehenden Nachrichten in einem Pub/Sub-Abo durchführen. Eine Liste aller unterstützten Messwertquellen finden Sie in der KEDA-Dokumentation.

    Installieren Sie KEDA auf Ihrem Cluster mit Helm oder mit kubectl.

    Helm

    Führen Sie die folgenden Befehle aus, um das KEDA-Helm-Repository hinzuzufügen, das KEDA-Helm-Diagramm zu installieren und dem KEDA-Dienstkonto Lesezugriff auf Cloud Monitoring zu gewähren:

    helm repo add kedacore https://kedacore.github.io/charts
    helm repo update
    helm install keda kedacore/keda --create-namespace --namespace keda
    
    gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
         --role roles/monitoring.viewer \
         --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
    

    Mit diesem Befehl werden auch Autorisierungsregeln eingerichtet, für die der Cluster mit der Identitätsföderation von Arbeitslasten für GKE eingerichtet sein muss.

    kubectl

    Führen Sie die folgenden Befehle aus, um KEDA mit kubectl apply zu installieren und dem KEDA-Dienstkonto Lesezugriff auf Cloud Monitoring zu gewähren:

    kubectl apply --server-side  -f https://github.com/kedacore/keda/releases/download/v2.15.1/keda-2.15.1.yaml
    
    gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
         --role roles/monitoring.viewer \
         --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
    

    Mit diesem Befehl werden auch Autorisierungsregeln eingerichtet, für die der Cluster mit der Identitätsföderation von Arbeitslasten für GKE eingerichtet sein muss.

    Prüfen Sie, ob alle KEDA-Ressourcen im Namespace keda angezeigt werden:

    kubectl get all -n keda
    

    Weitere Informationen zu KEDA-Design und -Ressourcen finden Sie in der KEDA-Dokumentation.

    Pub/Sub-Arbeitslast auf null skalieren

    In diesem Abschnitt wird ein Arbeitslast beschrieben, die Nachrichten aus einem Pub/Sub-Abo verarbeitet, jede Nachricht verarbeitet und den Abschluss bestätigt. Die Arbeitslast wird dynamisch skaliert: Wenn die Anzahl der nicht bestätigten Nachrichten zunimmt, werden durch das Autoscaling mehr Pods instanziiert, um eine zeitnahe Verarbeitung zu gewährleisten.

    Durch das Skalieren auf null wird dafür gesorgt, dass keine Pods instanziiert werden, wenn seit einiger Zeit keine Nachrichten empfangen wurden. Das spart Ressourcen, da keine Pods über längere Zeit im Leerlauf bleiben.

    Pub/Sub-Arbeitslast bereitstellen

    Stellen Sie eine Beispielarbeitslast bereit, die Nachrichten verarbeitet, die in einem Pub/Sub-Thema in die Warteschlange gestellt werden. Um eine realistische Arbeitslast zu simulieren, wartet dieses Beispielprogramm drei Sekunden, bevor es eine Nachricht bestätigt. Die Workload ist so konfiguriert, dass sie unter dem Dienstkonto keda-pubsub-sa ausgeführt wird.

    Führen Sie die folgenden Befehle aus, um das Pub/Sub-Thema und das Abo zu erstellen, die Berechtigung zu konfigurieren und die Bereitstellung zu erstellen, mit der die Arbeitslast im Namespace keda-pubsub gestartet wird.

    gcloud pubsub topics create keda-echo
    gcloud pubsub subscriptions create keda-echo-read --topic=keda-echo
    gcloud projects add-iam-policy-binding projects/${PROJECT_ID}  \
        --role=roles/pubsub.subscriber \
      --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda-pubsub/sa/keda-pubsub-sa
    
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-with-workload-identity.yaml
    

    Skalierung auf null konfigurieren

    Wenn Sie Ihre Pub/Sub-Arbeitslast so konfigurieren möchten, dass sie auf null skaliert wird, verwenden Sie KEDA, um eine ScaledObject-Ressource zu definieren, mit der angegeben wird, wie die Bereitstellung skaliert werden soll. KEDA erstellt und verwaltet dann automatisch das zugrunde liegende HorizontalPodAutoscaler-Objekt (HPA).

    1. Erstellen Sie die ScaledObject-Ressource, um das erwartete Autoscaling-Verhalten zu beschreiben:

      curl https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-scaledobject.yaml | envsubst | kubectl apply -f -
      

      Dadurch wird das folgende Objekt erstellt:

      apiVersion: keda.sh/v1alpha1
      kind: ScaledObject
      metadata:
        name: keda-pubsub
        namespace: keda-pubsub
      spec:
        maxReplicaCount: 5
        scaleTargetRef:
          name: keda-pubsub
        triggers:
          - type: gcp-pubsub
            authenticationRef:
              name: keda-auth
            metadata:
              subscriptionName: "projects/${PROJECT_ID}/subscriptions/keda-echo-read"
      
    2. Sehen Sie sich das HorizontalPodAutoscaler-Objekt (HPA) an, das KEDA basierend auf dem ScaledObject-Objekt erstellt:

      kubectl get hpa keda-hpa-keda-pubsub -n keda-pubsub -o yaml
      

      Weitere Informationen zum Autoscaling finden Sie in der Kubernetes-Dokumentation.

    3. Warten Sie, bis KEDA bestätigt, dass das Pub/Sub-Abo leer ist, und die Bereitstellung auf null Replikate skaliert.

      Arbeitslast-Autoscaler prüfen:

      kubectl describe hpa keda-hpa-keda-pubsub -n keda-pubsub
      

      Beachten Sie, dass die Bedingung ScalingActive in der Befehlsantwort falsch ist. Die zugehörige Meldung zeigt, dass das horizontale Pod-Autoscaling erkennt, dass KEDA das Deployment auf null skaliert hat. An diesem Punkt wird der Betrieb eingestellt, bis das Deployment wieder auf einen Pod skaliert wird.

      Name:                                                  keda-hpa-keda-pubsub
      Namespace:                                             keda-pubsub
      Metrics:                                               ( current / target )
        "s0-gcp-ps-projects-[...]]" (target average value):  0 / 10
      Min replicas:                                          1
      Max replicas:                                          5
      Deployment pods:                                       5 current / 5 desired
      Conditions:
        Type            Status  Reason               Message
        ----            ------  ------               -------
        AbleToScale     True    ScaleDownStabilized  recent recommendations were higher than current one [...]
        ScalingActive   False   ScalingDisabled      scaling is disabled since the replica count of the target is zero
        ScalingLimited  True    TooManyReplicas      the desired replica count is more than the maximum replica count
      

    Hochskalierung auslösen

    So stimulieren Sie das Deployment, um es zu skalieren:

    1. Nachrichten in die Warteschlange des Pub/Sub-Themas einreihen:

      for num in {1..20}
      do
        gcloud pubsub topics publish keda-echo --project=${PROJECT_ID} --message="Test"
      done
      
    2. Prüfen Sie, ob die Bereitstellung hochskaliert wird:

      kubectl get deployments -n keda-pubsub
      

      Beachten Sie in der Ausgabe, dass in der Spalte „Bereit“ ein Replikat angezeigt wird:

      NAME          READY   UP-TO-DATE   AVAILABLE   AGE
      keda-pubsub   1/1     1            1           2d
      

    KEDA skaliert die Bereitstellung hoch, nachdem festgestellt wurde, dass die Warteschlange nicht leer ist.

    LLM-Arbeitslast auf null skalieren

    In diesem Abschnitt wird eine LLM-Arbeitslast (Large Language Model) beschrieben, mit der ein Ollama-Server mit angehängter GPU bereitgestellt wird. Mit Ollama können beliebte LLMs wie Gemma und Llama 2 ausgeführt werden. Die Funktionen werden hauptsächlich über HTTP bereitgestellt.

    KEDA-HTTP-Add-on installieren

    Wenn ein HTTP-Dienst in Zeiten der Inaktivität auf null Pods skaliert wird, führt dies zu Anfragenfehlern, da kein Backend vorhanden ist, das die Anfragen verarbeiten kann.

    In diesem Abschnitt wird beschrieben, wie Sie dieses Problem mit dem KEDA-HTTP-Add-on beheben. KEDA-HTTP startet einen HTTP-Proxy, der Nutzeranfragen empfängt und an die Dienste weiterleitet, die für die Skalierung auf null konfiguriert sind. Wenn der Dienst keinen Pod hat, löst der Proxy eine Aufskalierung des Dienstes aus und puffert die Anfrage, bis der Dienst auf mindestens einen Pod skaliert wurde.

    Installieren Sie das KEDA-HTTP-Add-on mit Helm. Weitere Informationen finden Sie in der KEDA-HTTP-Dokumentation.

    helm repo add ollama-helm https://otwld.github.io/ollama-helm/
    helm repo update
    
    # Set the proxy timeout to 120s, giving Ollama time to start.
    helm install http-add-on kedacore/keda-add-ons-http  \
      --create-namespace --namespace keda \
      --set interceptor.responseHeaderTimeout=120s
    

    Ollama-LLM-Arbeitslast bereitstellen

    So stellen Sie eine Ollama-LLM-Arbeitslast bereit:

    1. Erstellen Sie einen Knotenpool mit g2-standard-4-Knoten mit angehängten GPUs und konfigurieren Sie das Cluster-Autoscaling so, dass zwischen null und zwei Knoten bereitgestellt werden:

      gcloud container node-pools create gpu --machine-type=g2-standard-4 \
          --location=${LOCATION} --cluster=scale-to-zero \
          --min-nodes 0 --max-nodes 2 --num-nodes=1 --enable-autoscaling
      
    2. Fügen Sie das offizielle Ollama-Helm-Diagramm-Repository hinzu und aktualisieren Sie das Repository Ihres lokalen Helm-Clients:

      helm repo add ollama-helm https://otwld.github.io/ollama-helm/
      helm repo update
      
    3. Stellen Sie den Ollama-Server mit dem Helm-Diagramm bereit:

      helm install ollama ollama-helm/ollama --create-namespace --namespace ollama \
        -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/helm-values-ollama.yaml
      

      In der helm-values-ollama.yaml-Konfiguration werden die zu ladenden LLM-Modelle, die GPU-Anforderungen und der TCP-Port für den Ollama-Server angegeben.

    Skalierung auf null konfigurieren

    Damit Ihre Ollama-Arbeitslast auf null skaliert werden kann, verwendet KEDA-HTTP ein HTTPScaledObject.

    1. Erstellen Sie die HTTPScaledObject-Ressource, um das erwartete Autoscaling-Verhalten zu beschreiben:

      kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/keda-ollama-httpscaledobject.yaml
      

      Dadurch wird das HTTPScaledObject-Objekt erstellt, das die folgenden Felder definiert:

      • scaleTargetRef: Gibt den Dienst an, an den KEDA-HTTP die Anfragen weiterleiten soll. In diesem Beispiel werden alle Anfragen mit dem Host ollama.ollama an den Ollama-Server weitergeleitet.
      • scaledownPeriod: Gibt in Sekunden an, wie schnell die Skalierung verringert werden soll, wenn keine Anfragen eingehen.
      • replicas: Gibt die Mindest- und Höchstanzahl der Pods an, die für die Ollama-Bereitstellung beibehalten werden sollen.
      • scalingMetric: Gibt die Messwerte an, die für das Autoscaling verwendet werden, z. B. die Anforderungsrate in diesem Beispiel. Weitere Messwertoptionen finden Sie in der KEDA-HTTP-Dokumentation.
      kind: HTTPScaledObject
      apiVersion: http.keda.sh/v1alpha1
      metadata:
          namespace: ollama
          name: ollama
      spec:
          hosts:
          - ollama.ollama
          scaleTargetRef:
              name: ollama
              kind: Deployment
              apiVersion: apps/v1
              service: ollama
              port: 11434
          replicas:
              min: 0
              max: 2
          scaledownPeriod: 3600
          scalingMetric:
              requestRate:
                  targetValue: 20
      
    2. Führen Sie den folgenden Befehl aus, um zu prüfen, ob KEDA-HTTP die im vorherigen Schritt erstellte HTTPScaledObject erfolgreich verarbeitet hat:

      kubectl get hpa,scaledobject -n ollama
      

      Die Ausgabe zeigt die Ressourcen HorizontalPodAutoscaler (von KEDA erstellt) und ScaledObject (von KEDA-HTTP erstellt):

      NAME                                                  REFERENCE           TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
      horizontalpodautoscaler.autoscaling/keda-hpa-ollama   Deployment/ollama   0/100 (avg)   1         2         1          2d
      
      NAME                          SCALETARGETKIND      SCALETARGETNAME   MIN   MAX   TRIGGERS        AUTHENTICATION   READY   ACTIVE   FALLBACK   PAUSED    AGE
      scaledobject.keda.sh/ollama   apps/v1.Deployment   ollama            0     2     external-push                    True    False    False      Unknown   2d
      
    3. Prüfen Sie, ob die Bereitstellung auf null Pods skaliert wird.

      Warten Sie den im Feld scaledownPeriod festgelegten Zeitraum ab und führen Sie den Befehl aus:

      kubectl get deployments -n ollama
      

      Die Ausgabe zeigt, dass KEDA das Ollama-Deployment skaliert hat und keine Pods ausgeführt werden:

      NAME     READY   UP-TO-DATE   AVAILABLE   AGE
      ollama   0/0     0            0           2d
      

    Hochskalierung auslösen

    Um die Bereitstellung zum Hochskalieren zu veranlassen, rufen Sie den Ollama-Dienst über den Proxy auf, der vom KEDA-HTTP-Add-on eingerichtet wurde. Dadurch erhöht sich der Wert des Messwerts Anfragerate und es wird ein erster Pod erstellt.

    Verwenden Sie die kubectl-Portweiterleitungsfunktionen, um auf den Proxy zuzugreifen, da der Proxy nicht extern verfügbar gemacht wird.

    kubectl port-forward svc/keda-add-ons-http-interceptor-proxy -n keda 8080:8080 &
    
    # Set the 'Host' HTTP header so that the proxy routes requests to the Ollama server.
    curl -H "Host: ollama.ollama" \
      http://localhost:8080/api/generate \
      -d '{ "model": "gemma:7b", "prompt": "Hello!" }'
    

    Mit dem Befehl curl wird der Prompt „Hallo!“ an ein Gemma-Modell gesendet. Sehen Sie sich die Antwort-Tokens an, die in der Antwort zurückgegeben werden. Die Spezifikation der API finden Sie im Ollama-Leitfaden.

    Bereinigen

    Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

    1. Bereinigen Sie das Pub/Sub-Abo und -Thema:

      gcloud pubsub subscriptions delete keda-echo-read
      gcloud pubsub topics delete keda-echo
      
    2. So löschen Sie den GKE-Cluster:

      gcloud container clusters delete scale-to-zero --location=${LOCATION}
      

    Nächste Schritte