Servir LLMs en GKE con una estrategia de aprovisionamiento de GPUs optimizada para los costes y de alta disponibilidad


En esta guía se explica cómo optimizar los costes de las cargas de trabajo de servicio de LLMs en GKE. En este tutorial se usa una combinación de máquinas virtuales de acceso puntual, de inicio flexible y de perfiles de clase de computación personalizados para realizar inferencias de forma rentable.

En esta guía se usa Mixtral 8x7b como ejemplo de LLM que puedes implementar.

Esta guía está dirigida a ingenieros de aprendizaje automático, administradores y operadores de plataformas, y especialistas en datos e IA que estén interesados en usar las funciones de orquestación de contenedores de Kubernetes para servir LLMs. Para obtener más información sobre los roles habituales y las tareas de ejemplo a las que hacemos referencia en el contenido, consulta Roles y tareas de usuario habituales de GKE. Google Cloud

Precios de inicio flexible

Se recomienda el inicio flexible si tu carga de trabajo requiere recursos aprovisionados dinámicamente según sea necesario, durante un máximo de siete días con reservas a corto plazo, sin una gestión de cuotas compleja y con un acceso rentable. La función de inicio flexible se basa en Dynamic Workload Scheduler y se factura según los precios de Dynamic Workload Scheduler:

  • Descuento (hasta el 53%) en vCPUs, GPUs y TPUs.
  • Pagas a medida que avanzas.

Fondo

En esta sección se describen las técnicas disponibles que puedes usar para obtener recursos de computación, incluidos los aceleradores de GPU, en función de los requisitos de tus cargas de trabajo de IA o aprendizaje automático. Estas técnicas se denominan estrategias de disponibilidad de aceleradores en GKE.

GPUs

Las unidades de procesamiento gráfico (GPUs) te permiten acelerar cargas de trabajo específicas, como el aprendizaje automático y el procesamiento de datos. GKE ofrece nodos equipados con estas potentes GPUs para optimizar el rendimiento de las tareas de aprendizaje automático y procesamiento de datos. GKE ofrece una serie de opciones de tipos de máquinas para la configuración de nodos, incluidos los tipos de máquinas con GPUs NVIDIA H100, A100 y L4.

Para obtener más información, consulta el artículo Acerca de las GPUs en GKE.

Modo de aprovisionamiento de inicio flexible

El modo de aprovisionamiento de inicio flexible, que se basa en Dynamic Workload Scheduler, es un tipo de consumo de GPU en el que GKE conserva tu solicitud de GPU y aprovisiona recursos automáticamente cuando hay capacidad disponible. Te recomendamos que uses el inicio flexible para las cargas de trabajo que necesiten capacidad de GPU durante un tiempo limitado (hasta siete días) y que no tengan una fecha de inicio fija. Para obtener más información, consulta flex-start.

Spot VMs

Puedes usar GPUs con máquinas virtuales de acceso puntual si tus cargas de trabajo pueden tolerar interrupciones frecuentes de los nodos. Si usas máquinas virtuales de acceso puntual o de inicio flexible, se reduce el precio de las GPUs. Si usas máquinas virtuales de Spot junto con la función de inicio flexible, tendrás una opción alternativa cuando no haya capacidad disponible en las máquinas virtuales de Spot.

Para obtener más información, consulta Usar VMs de acceso puntual con grupos de nodos de GPU.

Clases de computación personalizadas

Puedes solicitar GPUs mediante clases de computación personalizadas. Las clases de computación personalizadas te permiten definir una jerarquía de configuraciones de nodos para que GKE las priorice durante las decisiones de escalado de nodos, de modo que las cargas de trabajo se ejecuten en el hardware que hayas seleccionado. Para obtener más información, consulta el artículo Acerca de las clases de cálculo personalizadas.

Antes de empezar

  • 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.
  • 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 (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

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

  • 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 (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

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

  • Make sure that you have the following role or roles on the project:

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      Ir a IAM
    2. Selecciona el proyecto.
    3. Haz clic en Conceder acceso.
    4. En el campo Nuevos principales, introduce tu identificador de usuario. Normalmente, se trata de la dirección de correo de una cuenta de Google.

    5. En la lista Selecciona un rol, elige un rol.
    6. Para conceder más roles, haz clic en Añadir otro rol y añade cada rol adicional.
    7. Haz clic en Guardar.

Acceder al modelo

Si aún no tienes uno, genera un token de Hugging Face:

  1. Haz clic en Tu perfil > Configuración > Tokens de acceso.
  2. Selecciona New Token (Nuevo token).
  3. Especifica el nombre que quieras y un rol de al menos Read.
  4. Selecciona Generar un token.

Crear un perfil de clase de computación personalizado

En esta sección, crearás un perfil de clase de computación personalizado. Los perfiles de clase de computación personalizados definen los tipos y las relaciones entre los distintos recursos de computación que usa tu carga de trabajo.

  1. En la Google Cloud consola, inicia una sesión de Cloud Shell haciendo clic en Icono de activación de Cloud Shell Activar Cloud Shell en la Google Cloud consola. Se abrirá una sesión en el panel inferior de la consola Google Cloud .
  2. Crea un archivo de manifiesto dws-flex-start.yaml:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: dws-model-inference-class
    spec:
      priorities:
        - machineType: g2-standard-24
          spot: true
        - machineType: g2-standard-24
          flexStart:
            enabled: true
            nodeRecycling:
              leadTimeSeconds: 3600
      nodePoolAutoCreation:
        enabled: true
    
  3. Aplica el manifiesto dws-flex-start.yaml:

    kubectl apply -f dws-flex-start.yaml
    

GKE despliega g2-standard-24 máquinas con aceleradores L4. GKE usa clases de computación para priorizar las VMs de Spot y, en segundo lugar, las VMs de inicio flexible.

Desplegar la carga de trabajo de LLM

  1. Crea un secreto de Kubernetes que contenga el token de Hugging Face con el siguiente comando:

    kubectl create secret generic model-inference-secret \
        --from-literal=HUGGING_FACE_TOKEN=HUGGING_FACE_TOKEN \
        --dry-run=client -o yaml | kubectl apply -f -
    

    Sustituye HUGGING_FACE_TOKEN por tu token de acceso de Hugging Face.

  2. Crea un archivo llamado mixtral-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: inference-mixtral-ccc
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: llm
      template:
        metadata:
          labels:
            app: llm
        spec:
          nodeSelector:
            cloud.google.com/compute-class: dws-model-inference-class
          containers:
          - name: llm
            image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-generation-inference-cu124.2-3.ubuntu2204.py311
            resources:
              requests:
                cpu: "5"
                memory: "40Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "5"
                memory: "40Gi"
                nvidia.com/gpu: "2"
            env:
            - name: MODEL_ID
              value: mistralai/Mixtral-8x7B-Instruct-v0.1
            - name: NUM_SHARD
              value: "2"
            - name: PORT
              value: "8080"
            - name: QUANTIZE
              value: bitsandbytes-nf4
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: model-inference-secret
                  key: HUGGING_FACE_TOKEN
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
              - mountPath: /tmp
                name: ephemeral-volume
          volumes:
            - name: dshm
              emptyDir:
                  medium: Memory
            - name: ephemeral-volume
              ephemeral:
                volumeClaimTemplate:
                  metadata:
                    labels:
                      type: ephemeral
                  spec:
                    accessModes: ["ReadWriteOnce"]
                    storageClassName: "premium-rwo"
                    resources:
                      requests:
                        storage: 100Gi
    

    En este manifiesto, el campo mountPath se ha definido como /tmp, ya que es la ruta en la que se ha definido la variable de entorno HF_HOME en el contenedor de aprendizaje profundo (DLC) de la inferencia de generación de texto (TGI), en lugar de la ruta /data predeterminada que se ha definido en la imagen predeterminada de TGI. El modelo descargado se almacenará en este directorio.

  3. Despliega el modelo:

    kubectl apply -f  mixtral-deployment.yaml
    

    GKE programa un nuevo pod para implementarlo, lo que activa el autoescalador del grupo de nodos para añadir un segundo nodo antes de implementar la segunda réplica del modelo.

  4. Verifica el estado del modelo:

    watch kubectl get deploy inference-mixtral-ccc
    

    Si el modelo se ha implementado correctamente, el resultado será similar al siguiente:

    NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
    inference-mixtral-ccc  1/1     1            1           10m
    

    Para salir del reloj, pulsa CTRL + C.

  5. Espera a que se descargue el contenedor y empiece a servir el modelo:

    watch "kubectl logs $(kubectl get pods -l app=llm -o custom-columns=:metadata.name --no-headers) | tail"
    

    Para salir del reloj, pulsa CTRL + C.

  6. Consulta los grupos de nodos que ha aprovisionado GKE:

    kubectl get nodes -L cloud.google.com/gke-nodepool
    

    El resultado debería ser similar al siguiente:

      NAME                                                  STATUS   ROLES    AGE   VERSION               GKE-NODEPOOL
      gke-flex-na-nap-g2-standard--0723b782-fg7v   Ready    <none>   10m   v1.32.3-gke.1152000   nap-g2-standard-24-spot-gpu2-1gbdlbxz
      gke-flex-nap-zo-default-pool-09f6fe53-fzm8   Ready    <none>   32m   v1.32.3-gke.1152000   default-pool
      gke-flex-nap-zo-default-pool-09f6fe53-lv2v   Ready    <none>   32m   v1.32.3-gke.1152000   default-pool
      gke-flex-nap-zo-default-pool-09f6fe53-pq6m   Ready    <none>   32m   v1.32.3-gke.1152000   default-pool
    

    El nombre del grupo de nodos creado indica el tipo de máquina. En este caso, GKE ha aprovisionado máquinas virtuales de acceso puntual.

  7. Expón el modelo:

    kubectl expose deployment/inference-mixtral-ccc --port 8080 --name=llm-service
    

Interactuar con el modelo mediante curl

En esta sección se muestra cómo realizar una prueba de inferencia básica para verificar el modelo implementado.

  1. Configura la redirección de puertos al modelo:

    kubectl port-forward service/llm-service 8080:8080
    

    El resultado debería ser similar al siguiente:

    Forwarding from 127.0.0.1:8080 -> 8080
    
  2. En una nueva sesión de terminal, chatea con tu modelo usando curl:

    curl http://localhost:8080/v1/completions \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{
        "model": "mixtral-8x7b-instruct-gptq",
        "prompt": "<s>[INST]Who was the first president of the United States?[/INST]",
        "max_tokens": 40}'
    

    El resultado es similar al siguiente:

    George Washington was a Founding Father and the first president of the United States, serving from 1789 to 1797.
    

Limpieza

Para evitar que se apliquen cargos en tu Google Cloud cuenta por los recursos utilizados en esta página, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.

Eliminar el proyecto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Eliminar el recurso concreto

  1. Elimina los recursos de Kubernetes que has creado en esta guía:

    kubectl delete deployment inference-mixtral-ccc
    kubectl delete service llm-service
    kubectl delete computeclass dws-model-inference-class
    kubectl delete secret model-inference-secret
    
  2. Elimina el clúster:

    gcloud container clusters delete CLUSTER_NAME
    

Siguientes pasos