Servir un LLM con GKE Inference Gateway

En este tutorial se describe cómo desplegar un modelo de lenguaje grande (LLM) en Google Kubernetes Engine (GKE) con GKE Inference Gateway. El tutorial incluye pasos para configurar el clúster, desplegar el modelo, configurar GKE Inference Gateway y gestionar las solicitudes de LLM.

Este tutorial está dirigido a ingenieros de aprendizaje automático, administradores y operadores de plataformas, y especialistas en datos e IA que quieran desplegar y gestionar aplicaciones de LLM en GKE con GKE Inference Gateway.

Antes de leer esta página, asegúrese de que conoce los siguientes conceptos:

GKE Inference Gateway mejora GKE Gateway para optimizar el servicio de aplicaciones y cargas de trabajo de IA generativa en GKE. Proporciona una gestión y un escalado eficientes de las cargas de trabajo de IA, permite establecer objetivos de rendimiento específicos para cada carga de trabajo, como la latencia, y mejora el uso de los recursos, la observabilidad y la seguridad de la IA.

Antes de empezar

Antes de empezar, asegúrate de que has realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si quieres usar Google Cloud CLI para esta tarea, instálala y, a continuación, inicialízala. Si ya has instalado la CLI de gcloud, obtén la versión más reciente ejecutando el comando gcloud components update. Es posible que las versiones anteriores de la interfaz de línea de comandos de gcloud no admitan la ejecución de los comandos de este documento.
  • Habilita las APIs Compute Engine, Network Services y Model Armor si es necesario.

    Ve a Habilitar acceso a APIs y sigue las instrucciones.

  • Asegúrate de que tienes los siguientes roles en el proyecto: roles/container.admin y roles/iam.serviceAccountAdmin.

  • Asegúrate de que tu proyecto tenga suficiente cuota para las GPUs H100. Para obtener más información, consulta Planificar la cuota de GPU y Cuotas de asignación.

  • Crea una cuenta de Hugging Face si aún no tienes una. Lo necesitarás para acceder a los recursos del modelo de este tutorial.

  • Solicita acceso al modelo Llama 3.1 y genera un token de acceso. Para acceder a este modelo, debes enviar una solicitud aprobada en Hugging Face. Si no se te ha concedido acceso, la implementación fallará.

    • Firma el contrato de consentimiento de licencia: debes firmar el contrato de consentimiento para usar el modelo Llama 3.1. Ve a la página del modelo en Hugging Face, verifica tu cuenta y acepta los términos.
    • Genera un token de acceso: para acceder al modelo, necesitas un token de Hugging Face. En tu cuenta de Hugging Face, ve a Tu perfil > Configuración > Tokens de acceso, crea un token con al menos permisos de lectura y cópialo en el portapapeles.

Requisitos de GKE Gateway Controller

  • GKE 1.32.3 o una versión posterior.
  • Tener instalada la versión 407.0.0 o una posterior de la CLI de Google Cloud.
  • La API Gateway solo se admite en clústeres nativos de VPC.
  • Debes habilitar una subred de solo proxy.
  • Tu clúster debe tener habilitado el complemento HttpLoadBalancing.
  • Si usas Istio, debes actualizarlo a una de las siguientes versiones:
    • 1.15.2 o posterior
    • 1.14.5 o posterior
    • 1.13.9 o posterior
  • Si utilizas una VPC compartida, en el proyecto host debes asignar el rol Compute Network User a la cuenta de servicio de GKE del proyecto de servicio.

Restricciones y limitaciones

Se aplican las siguientes restricciones y limitaciones:

  • No se admiten las pasarelas multiclúster.
  • GKE Inference Gateway solo se admite en los recursos gke-l7-regional-external-managed y gke-l7-rilb GatewayClass.
  • No se admiten los balanceadores de carga de aplicación internos entre regiones.

Configurar GKE Inference Gateway

Para configurar GKE Inference Gateway, consulta este ejemplo. Un equipo ejecuta los modelos vLLM y Llama3, y experimenta activamente con dos adaptadores LoRA ajustados: "food-review" y "cad-fabricator".

El flujo de trabajo general para configurar GKE Inference Gateway es el siguiente:

  1. Prepara tu entorno: configura la infraestructura y los componentes necesarios.
  2. Crea un grupo de inferencia: define un grupo de servidores de modelos mediante el recurso personalizado InferencePool.
  3. Especificar objetivos de inferencia: especifica los objetivos de inferencia mediante el recurso personalizado InferenceObjective.
  4. Crea la pasarela: expón el servicio de inferencia mediante la API Gateway.
  5. Crea el HTTPRoute: define cómo se ruta el tráfico HTTP al servicio de inferencia.
  6. Enviar solicitudes de inferencia: envía solicitudes al modelo desplegado.

Prepara tu entorno

  1. Instala Helm.

  2. Crea un clúster de GKE:

    • Crea un clúster de Autopilot o Estándar de GKE con la versión 1.32.3 o posterior. Para ver una configuración de referencia de despliegue con un solo clic, consulta el cluster-toolkit gke-a3-highgpu ejemplo.
    • Configura los nodos con la familia de recursos de computación y el acelerador que prefieras.
    • Usa la guía de inicio rápido de inferencia en GKE para obtener archivos de manifiesto de implementación preconfigurados y probados en función del acelerador, el modelo y las necesidades de rendimiento que hayas seleccionado.
  3. Instala las definiciones de recursos personalizados (CRDs) necesarias en tu clúster de GKE:

    • En las versiones 1.34.0-gke.1626000 o posteriores de GKE, instala solo el CRD alfa InferenceObjective:

      kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/v1.0.0/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml
      
    • En las versiones de GKE anteriores a la 1.34.0-gke.1626000, instala los CRDs v1 InferencePool y alfa InferenceObjective:

      kubectl apply -f  https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.0.0/manifests.yaml
      

      Para obtener más información, consulta la matriz de compatibilidad.

  4. Si utilizas una versión de GKE anterior a la v1.32.2-gke.1182001 y quieres usar Model Armor con GKE Inference Gateway, debes instalar los CRDs de extensión de tráfico y de enrutamiento:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcptrafficextensions.yaml
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcproutingextensions.yaml
    

Crear un servidor de modelos y un despliegue de modelos

En esta sección se muestra cómo desplegar un servidor de modelos y un modelo. En el ejemplo se usa un servidor de modelos vLLM con un modelo Llama3. La implementación se etiqueta como app:vllm-llama3-8b-instruct. Esta implementación también usa dos adaptadores LoRA llamados food-review y cad-fabricator de Hugging Face.

Puedes adaptar este ejemplo con tu propio contenedor de servidor de modelos y modelo, puerto de servicio y nombre de implementación. También puedes configurar adaptadores LoRA en la implementación o implementar el modelo base. En los siguientes pasos se describe cómo crear los recursos de Kubernetes necesarios.

  1. Crea un secreto de Kubernetes para almacenar tu token de Hugging Face. Este token se usa para acceder al modelo base y a los adaptadores LoRA:

    kubectl create secret generic hf-token --from-literal=token=HF_TOKEN
    

    Sustituye HF_TOKEN por tu token de Hugging Face.

  2. Despliega el servidor de modelos y el modelo. El siguiente comando aplica un manifiesto que define un despliegue de Kubernetes para un servidor de modelos vLLM con un modelo Llama3:

    kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/release-1.0/config/manifests/vllm/gpu-deployment.yaml
    
    .

Crear un grupo de inferencia

El recurso personalizado de InferencePool Kubernetes define un grupo de pods con un modelo de lenguaje extenso (LLM) base común y una configuración de computación. El campo selector especifica qué pods pertenecen a este grupo. Las etiquetas de este selector deben coincidir exactamente con las etiquetas aplicadas a los pods de tu servidor de modelos. El campo targetPort define los puertos que usa el servidor de modelos en los pods. El campo extensionRef hace referencia a un servicio de extensión que proporciona funciones adicionales al grupo de inferencia. InferencePool permite que GKE Inference Gateway enrute el tráfico a los pods de tu servidor de modelos.

Antes de crear el InferencePool, asegúrate de que los pods que selecciona el InferencePool ya estén en ejecución.

Para crear un InferencePool con Helm, sigue estos pasos:

helm install vllm-llama3-8b-instruct \
  --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \
  --set provider.name=gke \
  --set inferenceExtension.monitoring.gke.enabled=true \
  --version v1.0.1 \
  oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool

Cambie el siguiente campo para que coincida con su implementación:

  • inferencePool.modelServers.matchLabels.app: la clave de la etiqueta usada para seleccionar los pods de tu servidor de modelos.

Para la monitorización, el raspado de métricas de Google Cloud Managed Service para Prometheus está habilitado de forma predeterminada.

  • Para inhabilitar esta función, añade la marca --set inferenceExtension.monitoring.gke.enabled=false al comando.
  • Si usas la monitorización predeterminada en un clúster de Autopilot de GKE, también debes añadir la marca --set provider.gke.autopilot=true.

La instalación de Helm instala automáticamente la política de tiempo de espera necesaria, el selector de endpoints y los pods necesarios para la observabilidad.

De esta forma, se crea un objeto InferencePool: vllm-llama3-8b-instruct que hace referencia a los servicios de endpoint del modelo en los pods. También crea una implementación del selector de endpoints llamado app:vllm-llama3-8b-instruct-epp para este InferencePool.

Especificar objetivos de inferencia

El recurso personalizado InferenceObjective le permite especificar la prioridad de las solicitudes.

El campo metadata.name del recurso InferenceObjective especifica el nombre del objetivo de inferencia, el campo Priority especifica su nivel de importancia y el campo poolRef especifica el InferencePool en el que se ofrece el modelo.

apiVersion: inference.networking.k8s.io/v1alpha2
kind: InferenceObjective
metadata:
  name: NAME
spec:
  priority: VALUE
  poolRef:
    name: INFERENCE_POOL_NAME
    group: "inference.networking.k8s.io"

Haz los cambios siguientes:

  • NAME: el nombre de tu objetivo de inferencia. Por ejemplo, food-review.
  • VALUE: la prioridad del objetivo de inferencia. Es un número entero en el que un valor más alto indica una solicitud más crítica. Por ejemplo, 10.
  • INFERENCE_POOL_NAME: el nombre del InferencePool que has creado en el paso anterior. Por ejemplo, vllm-llama3-8b-instruct.

Para crear un InferenceObjective, sigue estos pasos:

  1. Guarda el siguiente archivo de manifiesto como inference-objectives.yaml. Este manifiesto crea dos recursos InferenceObjective. La primera configura el food-review objetivo de inferencia en el vllm-llama3-8b-instruct InferencePool con una prioridad de 10. La segunda configura el llama3-base-model objetivo de inferencia para que se sirva con una prioridad más alta, 20.

    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceObjective
    metadata:
      name: food-review
    spec:
      priority: 10
      poolRef:
        name: vllm-llama3-8b-instruct
        group: "inference.networking.k8s.io"
    ---
    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceObjective
    metadata:
      name: llama3-base-model
    spec:
      priority: 20 # Higher priority
      poolRef:
        name: vllm-llama3-8b-instruct
    
  2. Aplica el manifiesto de ejemplo a tu clúster:

    kubectl apply -f inference-objectives.yaml
    

Crear la pasarela

El recurso Gateway es el punto de entrada del tráfico externo en tu clúster de Kubernetes. Define los listeners que aceptan conexiones entrantes.

GKE Inference Gateway funciona con las siguientes clases de Gateway:

  • gke-l7-rilb: para balanceadores de carga de aplicaciones internos regionales.
  • gke-l7-regional-external-managed: para balanceadores de carga de aplicaciones externos regionales.

Para obtener más información, consulta la documentación de Gateway Classes.

Para crear una pasarela, sigue estos pasos:

  1. Guarda el siguiente archivo de manifiesto de ejemplo como gateway.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
    spec:
      gatewayClassName: GATEWAY_CLASS
      listeners:
        - protocol: HTTP
          port: 80
          name: http
    

    Haz los cambios siguientes:

    • GATEWAY_NAME: nombre único de tu recurso Gateway. Por ejemplo, inference-gateway.
    • GATEWAY_CLASS: la clase Gateway que quieras usar. Por ejemplo, gke-l7-regional-external-managed.
  2. Aplica el manifiesto a tu clúster:

    kubectl apply -f gateway.yaml
    

Nota: Para obtener más información sobre cómo configurar TLS para proteger tu pasarela con HTTPS, consulta la documentación de GKE sobre la configuración de TLS.

Crea el HTTPRoute

El recurso HTTPRoute define cómo enruta GKE Gateway las solicitudes HTTP entrantes a los servicios de backend, como tu InferencePool. El recurso HTTPRoute especifica las reglas de coincidencia (por ejemplo, encabezados o rutas) y el backend al que se debe reenviar el tráfico.

  1. Para crear un HTTPRoute, guarda el siguiente manifiesto de ejemplo como httproute.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: HTTPROUTE_NAME
    spec:
      parentRefs:
      - name: GATEWAY_NAME
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: PATH_PREFIX
        backendRefs:
        - name: INFERENCE_POOL_NAME
          group: "inference.networking.k8s.io"
          kind: InferencePool
    

    Haz los cambios siguientes:

    • HTTPROUTE_NAME: un nombre único para tu recurso HTTPRoute. Por ejemplo, my-route.
    • GATEWAY_NAME: el nombre del recurso Gateway que has creado. Por ejemplo, inference-gateway.
    • PATH_PREFIX: el prefijo de ruta que usas para que coincidan las solicitudes entrantes. Por ejemplo, / para que coincida con todo.
    • INFERENCE_POOL_NAME: el nombre del recurso InferencePool al que quieras dirigir el tráfico. Por ejemplo, vllm-llama3-8b-instruct.
  2. Aplica el manifiesto a tu clúster:

    kubectl apply -f httproute.yaml
    

Enviar solicitud de inferencia

Una vez que hayas configurado GKE Inference Gateway, podrás enviar solicitudes de inferencia al modelo desplegado. De esta forma, puedes generar texto a partir de la petición que introduzcas y de los parámetros que especifiques.

Para enviar solicitudes de inferencia, sigue estos pasos:

  1. Define las siguientes variables de entorno:

    export GATEWAY_NAME=GATEWAY_NAME
    export PORT_NUMBER=PORT_NUMBER # Use 80 for HTTP
    

    Haz los cambios siguientes:

    • GATEWAY_NAME: el nombre de tu recurso Gateway.
    • PORT_NUMBER: el número de puerto que has configurado en la pasarela.
  2. Para obtener el endpoint de Gateway, ejecuta el siguiente comando:

    echo "Waiting for the Gateway IP address..."
    IP=""
    while [ -z "$IP" ]; do
      IP=$(kubectl get gateway/${GATEWAY_NAME} -o jsonpath='{.status.addresses[0].value}' 2>/dev/null)
      if [ -z "$IP" ]; then
        echo "Gateway IP not found, waiting 5 seconds..."
        sleep 5
      fi
    done
    
    echo "Gateway IP address is: $IP"
    PORT=${PORT_NUMBER}
    
  3. Para enviar una solicitud al endpoint /v1/completions mediante curl, ejecuta el siguiente comando:

    curl -i -X POST ${IP}:${PORT}/v1/completions \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer $(gcloud auth application-default print-access-token)' \
    -d '{
        "model": "MODEL_NAME",
        "prompt": "PROMPT_TEXT",
        "max_tokens": MAX_TOKENS,
        "temperature": "TEMPERATURE"
    }'
    

    Haz los cambios siguientes:

    • MODEL_NAME: el nombre del modelo o del adaptador LoRA que se va a usar.
    • PROMPT_TEXT: la petición de entrada del modelo.
    • MAX_TOKENS: número máximo de tokens que se generarán en la respuesta.
    • TEMPERATURE: controla la aleatoriedad de la salida. Usa el valor 0 para obtener resultados deterministas o un número más alto para obtener resultados más creativos.

En el siguiente ejemplo se muestra cómo enviar una solicitud de ejemplo a GKE Inference Gateway:

curl -i -X POST ${IP}:${PORT}/v1/completions -H 'Content-Type: application/json' -H 'Authorization: Bearer $(gcloud auth print-access-token)' -d '{
    "model": "food-review-1",
    "prompt": "What is the best pizza in the world?",
    "max_tokens": 2048,
    "temperature": "0"
}'

Ten en cuenta los siguientes comportamientos:

  • Cuerpo de la solicitud: el cuerpo de la solicitud puede incluir parámetros adicionales, como stop y top_p. Consulta la especificación de la API de OpenAI para ver la lista completa de opciones.
  • Gestión de errores: implementa una gestión de errores adecuada en el código de tu cliente para gestionar los posibles errores en la respuesta. Por ejemplo, comprueba el código de estado HTTP en la respuesta curl. Un código de estado que no sea 200 suele indicar un error.
  • Autenticación y autorización: en las implementaciones de producción, protege tu endpoint de API con mecanismos de autenticación y autorización. Incluya los encabezados adecuados (por ejemplo, Authorization) en sus solicitudes.

Siguientes pasos