Información general
En esta guía se explica cómo ofrecer modelos de lenguaje extensos (LLMs) de última generación, como DeepSeek-R1 671B o Llama 3.1 405B, en Google Distributed Cloud (solo software) en hardware desnudo mediante unidades de procesamiento gráfico (GPUs) en varios nodos.
En esta guía se muestra cómo usar tecnologías portátiles de código abierto (Kubernetes, vLLM y la API LeaderWorkerSet [LWS]) para desplegar y publicar cargas de trabajo de IA y aprendizaje automático en clústeres de hardware desnudo. Google Distributed Cloud amplía GKE para usarlo en un entorno local, al tiempo que ofrece las ventajas del control granular, la escalabilidad, la resiliencia, la portabilidad y la rentabilidad de GKE.
Fondo
En esta sección se describen las tecnologías clave que se usan en esta guía, incluidos los dos LLMs que se usan como ejemplos en esta guía: DeepSeek-R1 y Llama 3.1 405B.
DeepSeek-R1
DeepSeek-R1, un modelo de lenguaje extenso de 671.000 millones de parámetros de DeepSeek, se ha diseñado para la inferencia lógica, el razonamiento matemático y la resolución de problemas en tiempo real en diversas tareas basadas en texto. Google Distributed Cloud gestiona las demandas computacionales de DeepSeek-R1, lo que permite que este modelo aproveche sus funciones con recursos escalables, computación distribuida y redes eficientes.
Para obtener más información, consulta la documentación de DeepSeek.
Llama 3.1 405B
Llama 3.1 405B es un modelo de lenguaje extenso de Meta diseñado para una amplia gama de tareas de procesamiento del lenguaje natural, como la generación de texto, la traducción y la respuesta a preguntas. Google Distributed Cloud ofrece la sólida infraestructura necesaria para dar respuesta a las necesidades de entrenamiento y servicio distribuidos de modelos de esta escala.
Para obtener más información, consulta la documentación de Llama.
Servicio de Kubernetes gestionado de Google Distributed Cloud
Google Distributed Cloud ofrece una amplia gama de servicios, incluido Google Distributed Cloud (solo software) para bare metal, que es ideal para desplegar y gestionar cargas de trabajo de IA o aprendizaje automático en tu propio centro de datos. Google Distributed Cloud es un servicio gestionado de Kubernetes que simplifica el despliegue, el escalado y la gestión de aplicaciones en contenedores. Google Distributed Cloud proporciona la infraestructura necesaria, incluidos recursos escalables, computación distribuida y redes eficientes, para gestionar las demandas computacionales de los LLMs.
Para obtener más información sobre los conceptos clave de Kubernetes, consulta Empezar a aprender sobre Kubernetes. Para obtener más información sobre Google Distributed Cloud y cómo te ayuda a escalar, automatizar y gestionar Kubernetes, consulta la descripción general de Google Distributed Cloud (solo software) para bare metal.
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. Google Distributed Cloud admite nodos equipados con estas potentes GPUs, lo que te permite configurar tu clúster para obtener un rendimiento óptimo en las tareas de aprendizaje automático y procesamiento de datos. Google Distributed Cloud ofrece una serie de opciones de tipos de máquinas para la configuración de nodos, incluidos tipos de máquinas con GPUs NVIDIA H100, L4 y A100.
Para obtener más información, consulta Configurar y usar GPUs NVIDIA.
LeaderWorkerSet (LWS)
LeaderWorkerSet (LWS) es una API de implementación de Kubernetes que aborda patrones de implementación comunes de cargas de trabajo de inferencia de varios nodos de IA y aprendizaje automático. El servicio multinodo utiliza varios pods, cada uno de los cuales puede ejecutarse en un nodo diferente, para gestionar la carga de trabajo de inferencia distribuida. LWS permite tratar varios pods como un grupo, lo que simplifica la gestión del servicio de modelos distribuidos.
vLLM y servicio multihost
Cuando sirvas LLMs que requieran muchos recursos de computación, te recomendamos que uses vLLM y ejecutes las cargas de trabajo en GPUs.
vLLM es un framework de servicio de LLMs de código abierto muy optimizado que puede aumentar el rendimiento del servicio en GPUs. Incluye funciones como las siguientes:
Implementación optimizada de Transformer con PagedAttention
Agrupación continua para mejorar el rendimiento general del servicio
Servicio distribuido en varias GPUs
En el caso de los LLMs que requieren muchos recursos computacionales y no caben en un solo nodo de GPU, puedes usar varios nodos de GPU para servir el modelo. vLLM admite la ejecución de cargas de trabajo en GPUs con dos estrategias:
El paralelismo de tensores divide las multiplicaciones de matrices en la capa de transformador entre varias GPUs. Sin embargo, esta estrategia requiere una red rápida debido a la comunicación necesaria entre las GPUs, por lo que no es adecuada para ejecutar cargas de trabajo en varios nodos.
El paralelismo de la fase divide el modelo por capas, es decir, de forma vertical. Esta estrategia no requiere una comunicación constante entre las GPUs, por lo que es una mejor opción cuando se ejecutan modelos en varios nodos.
Puedes usar ambas estrategias en el servicio de varios nodos. Por ejemplo, si usas dos nodos con ocho GPUs H100 cada uno, puedes usar ambas estrategias:
Paralelismo de la fase de procesamiento bidireccional para fragmentar el modelo en los dos nodos
Paralelismo de tensores de ocho vías para fragmentar el modelo en las ocho GPUs de cada nodo
Para obtener más información, consulta la documentación de vLLM.
Objetivos
Prepara tu entorno con un clúster de Google Distributed Cloud en modo Autopilot o Standard.
Despliega vLLM en varios nodos de tu clúster.
Usa vLLM para servir el modelo a través de
curl
.
Antes de empezar
- Asegúrate de tener un clúster de hardware desnudo que funcione con al menos un grupo de nodos de trabajo que tenga dos nodos de trabajo, cada uno de ellos configurado con ocho GPUs NVIDIA H100 de 80 GB.
- Crea una cuenta de Hugging Face si aún no tienes una.
Acceder al modelo
Puedes usar los modelos Llama 3.1 405B o DeepSeek-R1.
DeepSeek-R1
.Generar un token de acceso
Si aún no tienes uno, genera un nuevo token de Hugging Face:
Haz clic en Tu perfil > Configuración > Tokens de acceso.
Selecciona New Token (Nuevo token).
Especifica el nombre que quieras y un rol de al menos
Read
.Selecciona Generar un token.
Llama 3.1 405B
.Generar un token de acceso
Si aún no tienes uno, genera un nuevo token de Hugging Face:
Haz clic en Tu perfil > Configuración > Tokens de acceso.
Selecciona New Token (Nuevo token).
Especifica el nombre que quieras y un rol de al menos
Read
.Selecciona Generar un token.
Preparar el entorno
Para configurar tu entorno, sigue estos pasos:
Define los siguientes parámetros en la estación de trabajo de administrador:
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export HF_TOKEN=HUGGING_FACE_TOKEN export IMAGE_NAME= gcr.io/PROJECT_ID/vllm-multihost/vllm-multihost:latest
Sustituye los siguientes valores:
PROJECT_ID
: el ID de proyecto asociado a tu clúster.HUGGING_FACE_TOKEN
: el token de Hugging Face generado en la sección anterior Obtener acceso al modelo.
Crear un secreto de Kubernetes para las credenciales de Hugging Face
Crea un secreto de Kubernetes que contenga el token de Hugging Face con el siguiente comando:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
Sustituye KUBECONFIG
por la ruta del archivo kubeconfig del clúster en el que quieras alojar el LLM.
Crear tu propia imagen multinodo de vLLM
Para facilitar la comunicación entre nodos de vLLM, puedes usar Ray. El repositorio LeaderWorkerSet proporciona un Dockerfile que incluye una secuencia de comandos bash para configurar Ray con vLLM.
Para crear tu propia imagen multinodo de vLLM, debes clonar el repositorio LeaderWorkerSet, crear una imagen Docker con el Dockerfile proporcionado (que configura Ray para la comunicación entre nodos) y, a continuación, enviar esa imagen a Artifact Registry para implementarla en Google Distributed Cloud.
Compila el contenedor
Para crear el contenedor, sigue estos pasos:
Clona el repositorio LeaderWorkerSet:
git clone https://github.com/kubernetes-sigs/lws.git
Crea la imagen.
cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile.GPU . -t vllm-multihost
Enviar la imagen a Artifact Registry
Para asegurarte de que tu implementación de Kubernetes pueda acceder a la imagen, almacénala en Artifact Registry dentro de tu proyecto de Google Cloud :
docker image tag vllm-multihost ${IMAGE_NAME}
docker push ${IMAGE_NAME}
Instalar LeaderWorkerSet
Para instalar LWS, ejecuta el siguiente comando:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
Valida que el controlador LeaderWorkerSet se esté ejecutando en el espacio de nombres lws-system
con el siguiente comando:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
El resultado debería ser similar al siguiente:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
Desplegar el servidor de modelos vLLM
Para implementar el servidor de modelos vLLM, sigue estos pasos:
Crea y aplica el archivo de manifiesto en función del LLM que quieras implementar.
DeepSeek-R1
Crea un manifiesto YAML,
vllm-deepseek-r1-A3.yaml
, para el modelo vLLM server:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model deepseek-ai/DeepSeek-R1 --tensor-parallel-size 8 --pipeline-parallel-size 2 --trust-remote-code --max-model-len 4096" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Aplica el manifiesto ejecutando el siguiente comando:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
Crea un manifiesto YAML,
vllm-llama3-405b-A3.yaml
, para el modelo vLLM server:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model meta-llama/Meta-Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Aplica el manifiesto ejecutando el siguiente comando:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
Consulta los registros del servidor de modelos en ejecución con el siguiente comando:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIG
La salida debería ser similar a la siguiente:
INFO 08-09 21:01:34 api_server.py:297] Route: /detokenize, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/models, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /version, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /v1/chat/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/embeddings, Methods: POST INFO: Started server process [7428] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
Aplicar el modelo
Configura la redirección de puertos al modelo ejecutando el siguiente comando:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
Interactuar con el modelo mediante curl
Para interactuar con el modelo mediante curl, sigue estas instrucciones:
DeepSeek-R1
En una nueva terminal, envía una solicitud al servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-R1",
"prompt": "I have four boxes. I put the red box on the bottom and put the blue box on top. Then I put the yellow box on top the blue. Then I take the blue box out and put it on top. And finally I put the green box on the top. Give me the final order of the boxes from bottom to top. Show your reasoning but be brief",
"max_tokens": 1024,
"temperature": 0
}'
La salida debería ser similar a la siguiente:
{
"id": "cmpl-f2222b5589d947419f59f6e9fe24c5bd",
"object": "text_completion",
"created": 1738269669,
"model": "deepseek-ai/DeepSeek-R1",
"choices": [
{
"index": 0,
"text": ".\n\nOkay, let's see. The user has four boxes and is moving them around. Let me try to visualize each step. \n\nFirst, the red box is placed on the bottom. So the stack starts with red. Then the blue box is put on top of red. Now the order is red (bottom), blue. Next, the yellow box is added on top of blue. So now it's red, blue, yellow. \n\nThen the user takes the blue box out. Wait, blue is in the middle. If they remove blue, the stack would be red and yellow. But where do they put the blue box? The instruction says to put it on top. So after removing blue, the stack is red, yellow. Then blue is placed on top, making it red, yellow, blue. \n\nFinally, the green box is added on the top. So the final order should be red (bottom), yellow, blue, green. Let me double-check each step to make sure I didn't mix up any steps. Starting with red, then blue, then yellow. Remove blue from the middle, so yellow is now on top of red. Then place blue on top of that, so red, yellow, blue. Then green on top. Yes, that seems right. The key step is removing the blue box from the middle, which leaves yellow on red, then blue goes back on top, followed by green. So the final order from bottom to top is red, yellow, blue, green.\n\n**Final Answer**\nThe final order from bottom to top is \\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}.\n</think>\n\n1. Start with the red box at the bottom.\n2. Place the blue box on top of the red box. Order: red (bottom), blue.\n3. Place the yellow box on top of the blue box. Order: red, blue, yellow.\n4. Remove the blue box (from the middle) and place it on top. Order: red, yellow, blue.\n5. Place the green box on top. Final order: red, yellow, blue, green.\n\n\\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 76,
"total_tokens": 544,
"completion_tokens": 468,
"prompt_tokens_details": null
}
}
Llama 3.1 405B
En una nueva terminal, envía una solicitud al servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3.1-405B-Instruct",
"prompt": "San Francisco is a",
"max_tokens": 7,
"temperature": 0
}'
La salida debería ser similar a la siguiente:
{"id":"cmpl-0a2310f30ac3454aa7f2c5bb6a292e6c",
"object":"text_completion","created":1723238375,"model":"meta-llama/Meta-Llama-3.1-405B-Instruct","choices":[{"index":0,"text":" top destination for foodies, with","logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":5,"total_tokens":12,"completion_tokens":7}}
Siguientes pasos
- Consulta más información sobre las GPUs en Google Distributed Cloud.
- Consulta el repositorio de GitHub y la documentación de vLLM.
- Explorar el repositorio de GitHub de LWS