Ajusta automáticamente la escala de la entrega de modelos de vLLM con métricas de GPU

En este instructivo, se describe cómo escalar automáticamente tus servicios de Cloud Run que entregan LLMs con vLLM en función de métricas de GPU personalizadas con el ajuste de escala automático de métricas externas de Cloud Run (CREMA).

Si bien Cloud Run realiza el ajuste de escala automático de forma predeterminada con el uso de CPU y la simultaneidad, las cargas de trabajo de inferencia que requieren un uso intensivo de la GPU a menudo necesitan un ajuste de escala automático basado en métricas de la cola, como la cantidad de solicitudes en ejecución o el uso de la caché de KV. CREMA integra el escalamiento automático basado en eventos (KEDA) de Kubernetes con Cloud Run para habilitar el escalamiento dinámico impulsado por las métricas de Prometheus. vLLM expone las métricas de Prometheus y las envía a Cloud Monitoring.

Objetivos

En este instructivo, podrás:

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.

Es posible que los usuarios nuevos de Google Cloud cumplan con los requisitos para acceder a una prueba gratuita.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud . Si es la primera vez que usas Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. 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

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

  4. 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

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

  6. Habilita las APIs de Cloud Run, Parameter Manager, Artifact Registry, Cloud Build, Secret Manager y Cloud Monitoring si alguna aún no está habilitada.

    Roles necesarios para habilitar las APIs

    Para habilitar APIs, necesitas el permiso serviceusage.services.enable. Si creaste el proyecto, es probable que ya tengas este permiso a través del rol de propietario (roles/owner). De lo contrario, puedes obtener este permiso a través del rol de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin). Obtén más información para otorgar roles.

    Habilitar las API

  7. Instala y, luego, inicializa gcloud CLI.
  8. Establece las variables de entorno que se usan en todo este instructivo:
    export PROJECT_ID=PROJECT_ID
    export REGION=us-central1
    export VLLM_SERVICE_NAME=vllm-service
    export MODEL_NAME=gemma-2-2b-it
    export REPO_NAME=vllm-repo
    export BUCKET_NAME=my-vllm-models-${PROJECT_ID}
    export CREMA_SERVICE_NAME=crema-service
    Reemplaza PROJECT_ID por el ID del proyecto de Google Cloud .
  9. Configura tu proyecto:
    gcloud config set project $PROJECT_ID
  10. Si aún no tienes una, crea una cuenta en Hugging Face. Luego, crea un token de lectura en el sitio de Hugging Face. Hugging Face solo muestra el token una vez. Guárdalo en una ubicación segura, ya que no podrás volver a verlo.
  11. Navega a la página del modelo gemma-2-2b-it en Hugging Face y acepta las condiciones del acuerdo del modelo.

Roles obligatorios

Para obtener los permisos que necesitas y completar el instructivo, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

Descarga y sube las ponderaciones del modelo a Cloud Storage

Descarga los pesos del modelo de Hugging Face y transfiérelos a un bucket de Cloud Storage para que estén disponibles para la entrega del modelo:

  1. Instala la CLI de Hugging Face:

    pip install -U "huggingface_hub[cli]"
    
  2. Descarga los pesos del modelo de forma local con la CLI de Hugging Face:

    export HF_TOKEN="HF_TOKEN"
    export LOCAL_DIR="/tmp/$MODEL_NAME"
    HF_HOME=/tmp/huggingface python -m huggingface_hub.cli.hf download google/$MODEL_NAME --token $HF_TOKEN --local-dir=$LOCAL_DIR
    

    Reemplaza HF_TOKEN por tu token de acceso de usuario de Hugging Face. El token debe comenzar con hf_ seguido de 35 caracteres alfanuméricos aleatorios (por ejemplo, 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).

  3. Crea un bucket de Cloud Storage y copia las ponderaciones descargadas:

    gcloud storage buckets create gs://$BUCKET_NAME \
        --project=$PROJECT_ID \
        --location=$REGION \
        --uniform-bucket-level-access
    
    gcloud storage cp -r $LOCAL_DIR gs://$BUCKET_NAME/
    

Envía la imagen del contenedor de vLLM a Artifact Registry

Extrae las imágenes de los contenedores de entrega de modelos y envíalas a un repositorio en Artifact Registry:

  1. Crea un repositorio de Docker en Artifact Registry:

    gcloud artifacts repositories create $REPO_NAME \
        --repository-format=docker \
        --location=$REGION \
        --description="vLLM Docker Images"
    
  2. Autentica el daemon de Docker local con el registro:

    gcloud auth configure-docker ${REGION}-docker.pkg.dev
    
  3. Extrae la imagen de vLLM, etiquétala y envíala a Artifact Registry:

    docker pull docker.io/vllm/vllm-openai:latest
    docker tag docker.io/vllm/vllm-openai:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/vllm-openai:latest
    docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/vllm-openai:latest
    

Implementa el servicio de escalador automático de CREMA

Configura los roles de la cuenta de servicio y los manifiestos de parámetros para CREMA antes de implementar el servicio de ajuste de escala automático.

Crea una cuenta de servicio personalizada

Crea una cuenta de servicio personalizada con los permisos mínimos requeridos para usar los recursos aprovisionados. Esta cuenta de servicio actúa como la identidad del autoescalador. Ejecuta el siguiente comando para crear la cuenta de servicio de CREMA:

export CREMA_SA="crema-autoscaler@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud iam service-accounts create crema-autoscaler \
    --description="Service account for Cloud Run CREMA to read metrics and scale workloads" \
    --display-name="CREMA Autoscaler System"

Otorga permisos adicionales a tu cuenta de servicio personalizada

Para escalar el servicio, otorga los siguientes permisos en la cuenta de servicio personalizada:

  1. Otorga permiso a tu cuenta de servicio de CREMA para leer desde Parameter Manager:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$CREMA_SA" \
        --role="roles/parametermanager.parameterViewer"
    
  2. Otorga permiso a tu cuenta de servicio de CREMA para escalar el servicio:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$CREMA_SA" \
        --role="roles/run.developer"
    
  3. Otorga a tu cuenta de servicio de CREMA el rol de usuario de la cuenta de servicio:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$CREMA_SA" \
        --role="roles/iam.serviceAccountUser"
    
  4. Otorga permiso a tu cuenta de servicio de CREMA para ver las métricas:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$CREMA_SA" \
        --role="roles/monitoring.viewer"
    

Crea y registra la configuración de CREMA

Define los umbrales y las reglas de escalamiento en un manifiesto de configuración de CREMA y regístralo en el Parameter Manager:

  1. Guarda la siguiente configuración como my-crema-config.yaml. Esta configuración activa el ajuste de escala cuando la cantidad de solicitudes en ejecución (vllm:num_requests_running) supera el valor 2:

    apiVersion: crema/v1
    kind: CremaConfig
    spec:
      pollingInterval: 15
      triggerAuthentications:
        - metadata:
            name: adc-trigger-auth
          spec:
            podIdentity:
              provider: gcp
      scaledObjects:
        - spec:
            scaleTargetRef:
              name: projects/PROJECT_ID/locations/us-central1/services/vllm-service
            minReplicaCount: 1
            maxReplicaCount: 5
            triggers:
              - type: prometheus
                authenticationRef:
                  name: adc-trigger-auth
                metadata:
                  serverAddress: https://monitoring.googleapis.com/v1/projects/PROJECT_ID/location/global/prometheus
                  metric: vllm:num_requests_running
                  query: sum(vllm:num_requests_running)
                  threshold: '2'
    
  2. Registra el archivo de configuración en Parameter Manager:

    gcloud parametermanager parameters create crema-config \
        --location=global \
        --parameter-format=YAML
    
    gcloud parametermanager parameters versions create 1 \
        --location=global \
        --parameter=crema-config \
        --payload-data-from-file=my-crema-config.yaml
    

Implementa el servicio de CREMA

Implementa la imagen de CREMA como un servicio interno en segundo plano en Cloud Run:

gcloud run deploy $CREMA_SERVICE_NAME \
    --image=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0 \
    --region=$REGION \
    --service-account="$CREMA_SA" \
    --no-allow-unauthenticated \
    --no-cpu-throttling \
    --cpu=1 \
    --memory=1Gi \
    --min-instances=1 \
    --max-instances=1 \
    --ingress=internal \
    --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-24/runtimes/java25 \
    --set-env-vars="CREMA_CONFIG=projects/$PROJECT_ID/locations/global/parameters/crema-config/versions/1,OUTPUT_SCALER_METRICS=True"

Configura los permisos del servicio de vLLM

Otorga permisos a la cuenta de servicio predeterminada de Compute Engine para exportar métricas y leer pesos del modelo desde Cloud Storage:

  1. Recupera tu número de proyecto:

    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
  2. Otorga permiso a tu cuenta de servicio para escribir métricas:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
        --role="roles/monitoring.metricWriter"
    
  3. Otorga permiso a tu cuenta de servicio para leer los pesos del modelo desde Cloud Storage:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
        --role="roles/storage.objectViewer"
    

Implementa el servicio de vLLM con el contenedor secundario de OpenTelemetry

Implementa tu contenedor principal de entrega de vLLM en Cloud Run con los pesos del modelo que se activan desde Cloud Storage. Dado que la implementación de servicios de varios contenedores con sidecars en Cloud Run requiere una especificación de servicio en formato YAML declarativo, debes configurar el motor principal de vLLM junto con un recopilador de sidecar de OpenTelemetry para recuperar y exportar las métricas de vLLM:

  1. Guarda la siguiente especificación de implementación de varios contenedores como vllm-service.yaml:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: vllm-service
      labels:
        cloud.googleapis.com/location: us-central1
      annotations:
        run.googleapis.com/scalingMode: manual
        run.googleapis.com/manualInstanceCount: "1"
    spec:
      template:
        metadata:
          annotations:
            run.googleapis.com/execution-environment: gen2
            run.googleapis.com/cpu-throttling: "false"
            run.googleapis.com/gpu-zonal-redundancy-disabled: "true"
            autoscaling.knative.dev/minScale: "1"
        spec:
          containerConcurrency: 80
          nodeSelector:
            run.googleapis.com/accelerator: nvidia-l4
          volumes:
            - name: gcs-volume
              csi:
                driver: gcsfuse.run.googleapis.com
                volumeAttributes:
                  bucketName: my-vllm-models-PROJECT_ID
          containers:
            # Primary container: vLLM serving engine
            - name: vllm-container
              image: us-central1-docker.pkg.dev/PROJECT_ID/vllm-repo/vllm-openai:latest
              ports:
                - containerPort: 8080
              resources:
                limits:
                  cpu: "4"
                  memory: 16Gi
                  nvidia.com/gpu: "1"
              args:
                - "--model"
                - "/gcs/gemma-2-2b-it"
                - "--port"
                - "8080"
                - "--max-model-len"
                - "2048"
                - "--chat-template"
                - "{% for msg in messages %}{{ msg['content'] }}{% endfor %}"
              volumeMounts:
                - name: gcs-volume
                  mountPath: /gcs
              startupProbe:
                httpGet:
                  path: /health
                  port: 8080
                periodSeconds: 10
                failureThreshold: 24
    
            # Sidecar container: OpenTelemetry Collector
            - name: otel-collector
              image: otel/opentelemetry-collector-contrib:latest
              resources:
                limits:
                  cpu: "1"
                  memory: 1Gi
              args:
                - |
                  --config=yaml:
                  receivers:
                    prometheus:
                      config:
                        scrape_configs:
                          - job_name: 'vllm'
                            scrape_interval: 10s
                            metrics_path: '/metrics'
                            static_configs:
                              - targets: ['localhost:8080']
                  processors:
                    resourcedetection:
                      detectors: [gcp]
                      timeout: 2s
                    transform:
                      metric_statements:
                        - context: datapoint
                          statements:
                            - set(attributes["exported_location"], attributes["location"])
                            - delete_key(attributes, "location")
                            - set(attributes["exported_cluster"], attributes["cluster"])
                            - delete_key(attributes, "cluster")
                            - set(attributes["exported_namespace"], attributes["namespace"])
                            - delete_key(attributes, "namespace")
                            - set(attributes["exported_job"], attributes["job"])
                            - delete_key(attributes, "job")
                            - set(attributes["exported_instance"], attributes["instance"])
                            - delete_key(attributes, "instance")
                  exporters:
                    googlemanagedprometheus:
                  service:
                    pipelines:
                      metrics:
                        receivers: [prometheus]
                        processors: [resourcedetection, transform]
                        exporters: [googlemanagedprometheus]
    
  2. Reemplaza la configuración del servicio existente por el manifiesto de varios contenedores:

    gcloud run services replace vllm-service.yaml
    

Verifica los registros del servicio de CREMA

  1. En la consola de Google Cloud , navega a la página de Cloud Run.
  2. Selecciona tu crema-service.
  3. Haz clic en la pestaña Registros y verifica que los ciclos de sondeo de métricas estén activos:

    [INFO] [METRIC-PROVIDER] Starting metric collection cycle
    [INFO] [METRIC-PROVIDER] Successfully fetched scaled object metrics ...
    [INFO] [METRIC-PROVIDER] Sending scale request ...
    [INFO] [SCALER] Received ScaleRequest ...
    [INFO] [SCALER] Current instances ...
    [INFO] [SCALER] Recommended instances ...
    

Ejecuta una prueba de carga

Para probar el ajuste de escala automático, ejecuta una secuencia de comandos de prueba de carga para enviar solicitudes simultáneas al servicio de vLLM:

  1. En tu directorio de trabajo, crea un archivo llamado load-test.sh y agrega el siguiente código:

    #!/bin/bash
    
    export SERVICE_URL=$(gcloud run services describe $VLLM_SERVICE_NAME --region $REGION --format='value(status.url)')
    
    echo "Launching 5 parallel heavy requests to trigger autoscaling..."
    
    for i in {1..5}; do
        curl -s -X POST "${SERVICE_URL}/v1/chat/completions" \
            -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
            -H "Content-Type: application/json" \
            -d "{
                \"model\": \"/gcs/${MODEL_NAME}\",
                \"messages\": [{\"role\": \"user\", \"content\": \"Write an exceptionally long, detailed, and exhaustive essay about the entire history of the universe from the Big Bang to the modern day.\"}]
            }" > /dev/null &
    done
    
    echo "All 5 requests dispatched. Waiting for requests to complete..."
    wait
    echo "Done."
    
  2. Haz que la secuencia de comandos sea ejecutable y ejecuta la prueba de carga:

    chmod +x load-test.sh
    ./load-test.sh
    
  3. Vuelve a revisar los registros de crema-service y el panel de métricas de Cloud Run para verificar que la cantidad de instancias recomendada se escale en respuesta a las solicitudes en cola.

Explora las métricas de vLLM en Cloud Monitoring

Después de ejecutar la prueba de carga, explora cómo el tráfico afecta las métricas de la entrega de modelos en Cloud Monitoring:

  1. En la consola de Google Cloud , ve a la página Explorador de métricas en Cloud Monitoring.

    Ir al Explorador de métricas

  2. Haz clic en Selecciona una métrica.

  3. Expande Prometheus Target > Vllm y selecciona cualquiera de las métricas disponibles que terminen en /gauge. Por ejemplo, selecciona prometheus/vllm:num_requests_running/gauge para ver el recuento de solicitudes activas durante la prueba de carga.

Como se describe en la documentación de las métricas de producción de vLLM, las métricas adicionales de vLLM que se exportan a Cloud Monitoring incluyen las siguientes:

  • prometheus/vllm:num_requests_waiting/gauge: Es la cantidad de solicitudes que esperan en la cola para ser procesadas por el motor de vLLM.
  • prometheus/vllm:num_requests_running/gauge: Es la cantidad de solicitudes que se ejecutan en lotes del modelo.
  • prometheus/vllm:gpu_cache_usage_perc/gauge: Es el porcentaje de memoria de caché de KV de la GPU que se utiliza.
  • prometheus/vllm:num_requests_swapped/gauge: Es la cantidad de solicitudes cuya caché de KV se intercambió a la memoria de la CPU del host debido a la presión de la memoria.

Si bien este instructivo realiza el ajuste de escala en función de vllm:num_requests_running, puedes usar cualquiera de estas métricas de vLLM en tu configuración de CREMA para personalizar las reglas de ajuste de escala automático de tus cargas de trabajo según el tamaño de la cola, el uso de la caché de KV o el intercambio de solicitudes.

A diferencia de las métricas de simultaneidad de solicitudes HTTP estándar que tratan todas las solicitudes por igual, las métricas internas de vLLM tienen en cuenta la huella de memoria dinámica de la GPU de diferentes longitudes de instrucciones. El ajuste de escala en vllm:num_requests_running te ayuda a escalar de forma proactiva en función de la carga real de la GPU. Esto mantiene un búfer de capacidad activo antes de que el servidor se vea obligado a poner en cola las solicitudes en vllm:num_requests_waiting, lo que protege a los usuarios de aumentos repentinos graves en la latencia del tiempo hasta el primer token (TTFT).

Realiza una limpieza

Para evitar cargos adicionales en tu cuenta de Google Cloud , borra todos los recursos que implementaste con este instructivo.

Borra el proyecto

Si creaste un proyecto nuevo para este instructivo, bórralo. Si usaste un proyecto existente y necesitas conservarlo sin los cambios que agregaste en este instructivo, borra los recursos que creaste para el instructivo.

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Elimina recursos de instructivos

  1. Borra el servicio de Cloud Run que implementaste en este instructivo. Los servicios de Cloud Run no generan costos hasta que reciben solicitudes.

    Para borrar tu servicio de Cloud Run, ejecuta el siguiente comando:

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME por el nombre del servicio

    También puedes borrar los servicios de Cloud Run desde la consola deGoogle Cloud .

  2. Quita la configuración predeterminada de la región gcloud que agregaste durante la configuración del instructivo:

     gcloud config unset run/region
    
  3. Quita la configuración del proyecto:

     gcloud config unset project
    
  4. Borra la configuración de CREMA asignada al Parameter Manager:

    gcloud parametermanager parameters delete crema-config \
        --location=global \
        --quiet
    
  5. Borra la cuenta de servicio personalizada que se creó para CREMA:

    gcloud iam service-accounts delete $CREMA_SA \
        --quiet
    
  6. Borra el bucket de Cloud Storage que contiene el modelo:

    gcloud storage rm --recursive gs://$BUCKET_NAME
    
  7. Borra otros Google Cloud recursos que creaste en este instructivo:

¿Qué sigue?