Skalierung auf null mit KEDA


In dieser Anleitung erfahren Sie, wie Sie Ihre GKE-Arbeitslasten mit KEDA auf null Pods skalieren. Wenn Sie die Bereitstellungen auf null Pods skalieren, sparen Sie Ressourcen in Zeiten ohne Aktivität (z. B. an Wochenenden und außerhalb der Geschäftszeiten) oder bei intermittierenden Arbeitslasten wie periodischen Jobs.

Lernziele

In dieser Anleitung werden die folgenden Anwendungsfälle beschrieben:

  • Pub/Sub-Arbeitslast auf null skalieren: Skalieren Sie die Anzahl der Pods proportional zur Anzahl der Nachrichten, die im Pub/Sub-Thema in der Warteschlange stehen. Wenn die Warteschlange leer ist, wird die Arbeitslast automatisch auf null Pods herunterskaliert.
  • Skalieren Sie die LLM-Arbeitslast auf null. 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 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

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-Tool zur Paketverwaltung.
  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.

    Go to project selector

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

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

    Enable the APIs

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

    Go to project selector

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

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

    Enable the APIs

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 der 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, führen Sie diesen Befehl noch einmal aus, um die Variablen neu festzulegen.

  2. Erstellen Sie einen GKE-Standardcluster mit aktivierter Cluster-Autoscaling und Workload Identity-Föderation 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 skalieren und von null Pods auf einen Pod hochskalieren. 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, weil keine Pods ausgeführt werden, kann das Autoscaling nicht auf Pod-Messwerte wie die CPU-Auslastung zurückgreifen. Daher ermöglicht KEDA das Abrufen von Messwerten, die außerhalb des Clusters stammen, mithilfe einer Implementierung der External Metrics API von Kubernetes. Mit dieser API können Sie automatisch auf Grundlage von Messwerten wie der Anzahl ausstehender Nachrichten in einem Pub/Sub-Abo skalieren. Eine Liste aller unterstützten Messwertquellen finden Sie in der KEDA-Dokumentation.

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

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

Hinweis: Mit diesem Befehl werden auch Autorisierungsregeln eingerichtet, für die der Cluster mit der Identitätsföderation von Arbeitslasten für GKE eingerichtet werden 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

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

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

kubectl get all -n keda

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

Pub/Sub-Arbeitslast auf null skalieren

In diesem Abschnitt wird eine 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 erstellt, um eine zeitnahe Verarbeitung zu ermöglichen.

Durch das Herunterskalieren auf null werden keine Pods instanziiert, wenn seit einiger Zeit keine Nachrichten mehr empfangen wurden. Dadurch werden Ressourcen gespart, da keine Pods über einen längeren Zeitraum inaktiv bleiben.

Pub/Sub-Arbeitslast bereitstellen

Beispielarbeitslast bereitstellen, die Nachrichten verarbeitet, die in einer Pub/Sub-Warteschlange anstehen Um eine realistische Arbeitslast zu simulieren, wartet dieses Beispielprogramm drei Sekunden, bevor eine Nachricht bestätigt wird. Die Arbeitslast 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, die die Arbeitslast unter dem Namespace keda-pubub startet.

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, definieren Sie mit KEDA eine ScaledObject-Ressource, um anzugeben, 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. Prüfen Sie das HorizontalPodAutoscaler-Objekt (HPA), das KEDA anhand des ScaledObject-Objekts 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 erkennt, dass das Pub/Sub-Abo leer ist, und skaliert die Bereitstellung auf null Replikat.

    Prüfen Sie den Workload-Autoscaler:

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

    Beachten Sie, dass in der Befehlsantwort die Bedingung ScalingActive auf „falsch“ gesetzt ist. Die zugehörige Meldung zeigt, dass der horizontale Pod-Autoscaler erkennt, dass KEDA das Deployment auf null skaliert hat. Er wird dann angehalten, 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 regen Sie das Deployment zur Skalierung an:

  1. Nachrichten in der Warteschlange des Pub/Sub-Themas platzieren:

    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
    

    In der Ausgabe wird in der Spalte „Bereit“ ein Replikat angezeigt:

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

KEDA skaliert die Bereitstellung, sobald die Warteschlange nicht leer ist.

LLM-Arbeitslast auf null skalieren

In diesem Abschnitt wird eine LLM-Arbeitslast (Large Language Model) beschrieben, bei der ein Ollama-Server mit angeschlossener GPU bereitgestellt wird. Ollama ermöglicht das Ausführen beliebter LLMs wie Gemma und Llama 2 und stellt seine Funktionen hauptsächlich über HTTP bereit.

KEDA-HTTP-Add-on installieren

Wenn Sie einen HTTP-Dienst während der Inaktivität auf null Pods skalieren, kommt es zu Fehlern bei Anfragen, da es kein Backend gibt, das die Anfragen verarbeiten kann.

In diesem Abschnitt wird beschrieben, wie Sie dieses Problem mit dem Add-on KEDA-HTTP 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 die Skalierung 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 die 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

Um Ihre Ollama-Arbeitslast so zu konfigurieren, dass sie auf null skaliert, verwendet KEDA-HTTP eine 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 herunterskaliert werden soll, wenn keine Anfragen eingehen.
    • replicas: Gibt die minimale und maximale Anzahl von 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 Anfragerate in diesem Beispiel. Weitere Messoptionen 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 herunterskaliert wird.

    Warten Sie die im Feld scaledownPeriod festgelegte Zeitspanne ab und führen Sie den Befehl aus:

    kubectl get deployments -n ollama
    

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

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

Hochskalierung auslösen

Wenn Sie die Bereitstellung skalieren möchten, rufen Sie den Ollama-Dienst über den vom KEDA-HTTP-Add-on eingerichteten Proxy auf. Dadurch erhöht sich der Wert des Messwerts Anfragerate und der erste Pod wird erstellt.

Verwenden Sie die Portweiterleitungsfunktionen von kubectl, um auf den Proxy zuzugreifen, da der Proxy nicht extern verfügbar ist.

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!" }'

Der Befehl curl sendet den Prompt „Hallo!“ an ein Gemma-Modell. Beobachten Sie die Antworttokens, die in der Antwort zurückgegeben werden. Die Spezifikation der API findest du 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