Scalabilità fino a zero utilizzando KEDA


Questo tutorial mostra come ridurre i workload GKE a zero Pod utilizzando KEDA. La scalabilità dei deployment a zero pod consente di risparmiare risorse durante i periodi di inattività (ad esempio i fine settimana e le ore di chiusura dell'ufficio) o per i carichi di lavoro intermittenti come i job periodici.

Obiettivi

Questo tutorial descrive i seguenti casi d'uso:

  • Scala il carico di lavoro Pub/Sub a zero: scala il numero di pod in proporzione al numero di messaggi in coda nell'argomento Pub/Sub. Quando la coda è vuota, il carico di lavoro viene ridotto automaticamente a zero pod.
  • Scala il carico di lavoro LLM a zero. Esegui il deployment dei server dei modelli LLM su nodi con GPU. Quando il servizio è inattivo, il carico di lavoro viene ridotto automaticamente a zero pod.

Costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud potrebbero essere idonei per una prova gratuita.

Al termine delle attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la sezione Pulizia.

Prima di iniziare

In questo tutorial utilizzerai Cloud Shell per eseguire comandi. Cloud Shell è un ambiente shell per la gestione delle risorse ospitate su Google Cloud. È preinstallato con gli strumenti a riga di comando Google Cloud CLI, kubectl, Helm e Terraform. Se non utilizzi Cloud Shell, devi installare Google Cloud CLI e Helm.

  1. Per eseguire i comandi in questa pagina, configura gcloud CLI in uno dei seguenti ambienti di sviluppo:

    Cloud Shell

    Per utilizzare un terminale online con gcloud CLI già configurato, attiva Cloud Shell:

    Nella parte inferiore di questa pagina viene avviata una sessione di Cloud Shell e visualizzato un prompt della riga di comando. L'inizializzazione della sessione può richiedere alcuni secondi.

    Shell locale

    Per utilizzare un ambiente di sviluppo locale:

    1. Installa la gcloud CLI.
    2. Inizializza la gcloud CLI.
    3. Installa Helm, uno strumento di gestione dei pacchetti Kubernetes.
  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

Configurazione dell'ambiente

Per configurare l'ambiente con Cloud Shell:

  1. Imposta le variabili di ambiente:

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

    Sostituisci PROJECT_ID con il tuo ID progetto Google Cloud e LOCATION con le regioni o le zone in cui deve essere creato il tuo cluster GKE.

    Se non segui l'intero tutorial in una singola sessione o se le variabili di ambiente non sono impostate per qualche motivo, assicurati di eseguire di nuovo questo comando per impostarle di nuovo.

  2. Crea un cluster GKE standard con la scalabilità automatica del cluster e la federazione delle identità per i carichi di lavoro per GKE attivate:

    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
    

Installa KEDA

KEDA è un componente che integra Kubernetes Horizontal Pod Autoscaler. Con KEDA, puoi scalare un deployment a zero pod e da zero pod a un pod. L'algoritmo Horizontal Pod Autoscaler standard si applica dopo che GKE ha creato almeno un pod.

Dopo che GKE ha scalato il deployment a zero pod, poiché non sono in esecuzione, la scalabilità automatica non può fare affidamento sulle metriche dei pod come l'utilizzo della CPU. Di conseguenza, KEDA consente di recuperare le metriche provenienti dall'esterno del cluster utilizzando un'implementazione dell'API External Metrics di Kubernetes. Puoi utilizzare questa API per eseguire la scalabilità automatica in base a metriche come il numero di messaggi in sospeso in una sottoscrizione Pub/Sub. Consulta la documentazione di KEDA per un elenco di tutte le origini delle metriche supportate.

Installa KEDA sul tuo cluster con Helm o con kubectl.

Helm

Esegui i seguenti comandi per aggiungere il repository Helm KEDA, installare il grafico Helm KEDA e concedere all'account di servizio KEDA l'accesso in lettura a Cloud Monitoring:

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

Tieni presente che questo comando configura anche le regole di autorizzazione che richiedono la configurazione del cluster con Workload Identity Federation for GKE.

kubectl

Esegui i seguenti comandi per installare KEDA utilizzando kubectl apply e per concedere all'account di servizio KEDA l'accesso in lettura a Cloud Monitoring:

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

Tieni presente che questo comando configura anche le regole di autorizzazione che richiedono la configurazione del cluster con Workload Identity Federation for GKE.

Verifica che tutte le risorse KEDA vengano visualizzate nello spazio dei nomi keda:

kubectl get all -n keda

Per ulteriori informazioni sul design e sulle risorse di KEDA, consulta la documentazione di KEDA.

Scala il carico di lavoro Pub/Sub fino a zero

Questa sezione descrive un carico di lavoro che elabora i messaggi da una sottoscrizione Pub/Sub, gestisce ogni messaggio e ne conferma il completamento. Il carico di lavoro viene scalato in modo dinamico: con l'aumento del numero di messaggi non confermati, la scalabilità automatica esegue l'inizializzazione di più pod per garantire un'elaborazione tempestiva.

La scalabilità a zero garantisce che non vengano attivati pod se non vengono ricevuti messaggi da un po' di tempo. In questo modo si risparmiano risorse perché nessun pod rimane inattivo per lunghi periodi di tempo.

Esegui il deployment di un carico di lavoro Pub/Sub

Esegui il deployment di un carico di lavoro di esempio che elabora i messaggi in coda in un argomento Pub/Sub. Per simulare un carico di lavoro realistico, questo programma di esempio attende tre secondi prima di confermare un messaggio. Il carico di lavoro è configurato per essere eseguito con l'account di serviziokeda-pubsub-sa.

Esegui i seguenti comandi per creare l'argomento e la sottoscrizione Pub/Sub, configurare la relativa autorizzazione e creare il deployment avviando il carico di lavoro nello spazio dei nomi keda-pubub.

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://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-with-workload-identity.yaml

Configura la scalabilità fino a zero

Per configurare il carico di lavoro Pub/Sub in modo che sia scalabile a zero, utilizza KEDA per definire una risorsa ScaledObject per specificare come deve essere scalato il deployment. KEDA creerà e gestirà automaticamente l'oggetto HorizontalPodAutoscaler (HPA) di base.

  1. Crea la risorsa ScaledObject per descrivere il comportamento della scalabilità automatica previsto:

    envsubst < https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-scaledobject.yaml | kubectl apply -f -
    

    Viene creato il seguente oggetto:

    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. Controlla l'oggetto HorizontalPodAutoscaler (HPA) creato da KEDA in base all'oggetto ScaledObject:

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

    Puoi scoprire di più sulla scalabilità automatica nella documentazione di Kubernetes.

  3. Attendi che KEDA confermi che l'abbonamento Pub/Sub è vuoto e scala il deployment a zero repliche.

    Controlla il gestore della scalabilità automatica del carico di lavoro:

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

    Nota che nella risposta del comando, la condizione ScalingActive è falsa. Il messaggio associato mostra che Horizontal Pod Autoscaler conferma che KEDA ha ridotto il deployment a zero, a quel punto smette di funzionare fino a quando il deployment non esegue nuovamente lo scale up a un pod.

    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
    

Attivare il ridimensionamento in aumento

Per stimolare il deployment a eseguire lo scaling up:

  1. Inserisci in coda i messaggi nell'argomento Pub/Sub:

    for num in {1..20}
    do
      gcloud pubsub topics publish keda-echo --project=${PROJECT_ID} --message="Test"
    done
    
  2. Verifica che il deployment sia in fase di ridimensionamento:

    kubectl get deployments -n keda-pubsub
    

    Nell'output, noterai che la colonna "Pronta" mostra una replica:

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

KEDA esegue l'aumento di scala del deployment dopo aver notato che la coda non è vuota.

Riduci a zero il carico di lavoro LLM

Questa sezione descrive un carico di lavoro di modelli linguistici di grandi dimensioni (LLM) che esegue il deployment di un server Ollama con GPU collegata. Ollama consente di eseguire LLM di uso comune come Gemma e Llama 2 e mette a disposizione le sue funzionalità principalmente tramite HTTP.

Installa il componente aggiuntivo KEDA-HTTP

Lo scale down di un servizio HTTP a zero pod durante i periodi di inattività causa errori di richiesta, poiché non esiste un backend per gestire le richieste.

Questa sezione mostra come risolvere il problema utilizzando il componente aggiuntivo KEDA-HTTP. KEDA-HTTP avvia un proxy HTTP che riceve le richieste degli utenti e le inoltra ai servizi configurati per il ridimensionamento a zero. Quando il servizio non ha pod, il proxy attiva l'aumento di scalabilità del servizio e mette in buffer la richiesta finché il servizio non ha eseguito l'aumento di scalabilità fino ad almeno un pod.

Installa il componente aggiuntivo KEDA-HTTP utilizzando Helm. Per saperne di più, consulta la documentazione di KEDA-HTTP.

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

Esegui il deployment di un carico di lavoro LLM di Ollama

Per eseguire il deployment di un carico di lavoro LLM di Ollama:

  1. Crea un pool di nodi contenente g2-standard-4 nodi con GPU collegate e configura la scalabilità automatica del cluster per fornire da zero a due nodi:

    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. Aggiungi il repository ufficiale dei grafici Helm di Ollama e aggiorna il repository del client Helm locale:

    helm repo add ollama-helm https://otwld.github.io/ollama-helm/
    helm repo update
    
  3. Esegui il deployment del server Ollama utilizzando il grafico Helm:

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

    La configurazione helm-values-ollama.yaml specifica i modelli LLM da caricare, i requisiti della GPU e la porta TCP per il server Ollama.

Configura la scalabilità fino a zero

Per configurare il carico di lavoro Ollama in modo che sia scalabile a zero, KEDA-HTTP utilizza un HTTPScaledObject.

  1. Crea la risorsa HTTPScaledObject per descrivere il comportamento della scalabilità automatica previsto:

    kubectl apply -f https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/ollama/keda-ollama-httpscaledobject.yaml
    

    Viene creato l'oggetto HTTPScaledObject che definisce i seguenti campi:

    • scaleTargetRef: specifica il servizio a cui KEDA-HTTP deve inoltrare le richieste. In questo esempio, tutte le richieste con l'host ollama.ollama vengono inoltrate al server Ollama.
    • scaledownPeriod: specifica (in secondi) la velocità di fare lo scale down quando non vengono ricevute richieste.
    • replicas: specifica il numero minimo e massimo di pod da mantenere per il deployment di Ollama.
    • scalingMetric: specifica le metriche utilizzate per gestire la scalabilità automatica, ad esempio la frequenza delle richieste in questo esempio. Per altre opzioni di metrica, consulta la documentazione di KEDA-HTTP.
    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. Esegui il seguente comando per verificare che KEDA-HTTP abbia elaborato correttamente il HTTPScaledObject creato nel passaggio precedente.

    kubectl get hpa,scaledobject -n ollama
    

    L'output mostra le risorse HorizontalPodAutoscaler (create da KEDA) e ScaledObject (create da KEDA-HTTP):

    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. Verifica che il deployment riduca il numero di pod a zero.

    Attendi il periodo di tempo impostato nel campo scaledownPeriod ed esegui il comando:

    kubectl get deployments -n ollama
    

    L'output mostra che KEDA ha ridotto il deployment di Ollama e che nessun pod è in esecuzione:

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

Attivare il ridimensionamento in aumento

Per stimolare l'aumento di scala del deployment, chiama il servizio Ollama utilizzando il proxy impostato dal componente aggiuntivo KEDA-HTTP. Di conseguenza, il valore della metrica tasso di richieste aumenta e viene attivata la creazione di un primo pod.

Utilizza le funzionalità di inoltro delle porte kubectl per accedere al proxy perché il proxy non è esposto esternamente.

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

Il comando curl invia il prompt "Un saluto da Google" a un modello Gemma. Osserva i token di risposta che vengono restituiti nella risposta. Per la specifica dell'API, consulta la guida di Ollama.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

  1. Esegui la pulizia dell'argomento e della sottoscrizione Pub/Sub:

    gcloud pubsub subscriptions delete keda-echo-read
    gcloud pubsub topics delete keda-echo
    
  2. Elimina il cluster GKE:

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

Passaggi successivi