Utiliser vLLM sur GKE pour exécuter l'inférence avec Qwen3

Ce tutoriel explique comment déployer et diffuser un grand modèle de langage (LLM) Qwen3 avec le framework de diffusion vLLM. Vous déployez le modèle sur une seule instance de machine virtuelle A4 sur Google Kubernetes Engine (GKE).

Ce tutoriel est destiné aux ingénieurs en machine learning (ML), aux administrateurs et opérateurs de plate-forme, ainsi qu'aux spécialistes des données et de l'IA qui souhaitent utiliser les fonctionnalités d'orchestration de conteneurs Kubernetes pour gérer les charges de travail d'inférence.

Objectifs

  1. Accédez à Qwen3 à l'aide de Hugging Face.

  2. Préparez votre environnement.

  3. Créer un cluster GKE en mode Autopilot

  4. créer un bucket Cloud Storage ;

  5. Créez un secret Kubernetes pour les identifiants Hugging Face.

  6. Configurez la fédération d'identité de charge de travail pour Cloud Storage.

  7. Remplissez le bucket Cloud Storage avec le modèle Qwen3.

  8. Déployer un conteneur vLLM sur votre cluster GKE.

  9. Interagissez avec Qwen3 à l'aide de curl.

  10. Effectuer un nettoyage.

Coûts

Ce tutoriel fait appel à des composants payants de Google Cloud, y compris :

Vous pouvez obtenir une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  2. Installez la Google Cloud CLI.

  3. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.

  4. Pour initialiser la gcloud CLI, exécutez la commande suivante :

    gcloud init
  5. Créez ou sélectionnez un projet Google Cloud .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.
    • Créez un projet Google Cloud  :

      gcloud projects create PROJECT_ID

      Remplacez PROJECT_ID par le nom du projet Google Cloud que vous créez.

    • Sélectionnez le projet Google Cloud que vous avez créé :

      gcloud config set project PROJECT_ID

      Remplacez PROJECT_ID par le nom de votre projet Google Cloud .

  6. Vérifiez que la facturation est activée pour votre projet Google Cloud .

  7. Activez l'API requise :

    Rôles requis pour activer les API

    Pour activer les API, vous devez disposer de l'autorisation serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.

    gcloud services enable container.googleapis.com
  8. Installez la Google Cloud CLI.

  9. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à la gcloud CLI avec votre identité fédérée.

  10. Pour initialiser la gcloud CLI, exécutez la commande suivante :

    gcloud init
  11. Créez ou sélectionnez un projet Google Cloud .

    Rôles requis pour sélectionner ou créer un projet

    • Sélectionnez un projet : la sélection d'un projet ne nécessite pas de rôle IAM spécifique. Vous pouvez sélectionner n'importe quel projet pour lequel un rôle vous a été attribué.
    • Créer un projet : pour créer un projet, vous devez disposer du rôle Créateur de projet (roles/resourcemanager.projectCreator), qui contient l'autorisation resourcemanager.projects.create. Découvrez comment attribuer des rôles.
    • Créez un projet Google Cloud  :

      gcloud projects create PROJECT_ID

      Remplacez PROJECT_ID par le nom du projet Google Cloud que vous créez.

    • Sélectionnez le projet Google Cloud que vous avez créé :

      gcloud config set project PROJECT_ID

      Remplacez PROJECT_ID par le nom de votre projet Google Cloud .

  12. Vérifiez que la facturation est activée pour votre projet Google Cloud .

  13. Activez l'API requise :

    Rôles requis pour activer les API

    Pour activer les API, vous devez disposer de l'autorisation serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.

    gcloud services enable container.googleapis.com
  14. Attribuez des rôles à votre compte utilisateur. Exécutez la commande suivante une fois pour chacun des rôles IAM suivants : roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de votre projet
    • USER_IDENTIFIER : identifiant de votre compte utilisateur . Par exemple, myemail@example.com.
    • ROLE : rôle IAM que vous accordez à votre compte utilisateur.
  15. Connectez-vous à votre compte Hugging Face ou créez-en un.

Accéder à Qwen3 à l'aide de Hugging Face

Pour utiliser Hugging Face afin d'accéder à Qwen3, procédez comme suit :

  1. Se connecter à Hugging Face
  2. Créez un jeton d'accès read Hugging Face. Cliquez sur Votre profil > Paramètres > Jetons d'accès > + Créer un jeton.
  3. Donnez le nom de votre choix au jeton, puis sélectionnez un rôle. Le niveau d'autorisation minimal que vous pouvez sélectionner pour ce tutoriel est Lecture.
  4. Sélectionnez Créer un jeton.
  5. Copiez le jeton généré dans le presse-papiers et enregistrez-le. Vous en aurez besoin dans la suite de ce tutoriel.

Préparer votre environnement

Pour préparer votre environnement, définissez les variables d'environnement par défaut :

export PROJECT_ID="YOUR_PROJECT_ID"
export RESERVATION_NAME="YOUR_RESERVATION_NAME"
export REGION="YOUR_REGION"
export CLUSTER_NAME="YOUR_CLUSTER_NAME"
export GCS_BUCKET_NAME="YOUR_GCS_BUCKET"
export HUGGING_FACE_TOKEN="YOUR_HF_TOKEN"
export NETWORK="YOUR_NETWORK_NAME"
export SUBNETWORK="YOUR_SUBNETWORK_NAME"

gcloud config set project "${PROJECT_ID}"
gcloud config set billing/quota_project "${PROJECT_ID}"

Remplacez les éléments suivants :

  • YOUR_PROJECT_ID : ID du Google Cloud projet dans lequel vous souhaitez créer le cluster GKE.

  • YOUR_RESERVATION_NAME : nom de la réservation que vous souhaitez utiliser pour créer votre cluster GKE. En fonction du projet dans lequel la réservation existe, spécifiez l'une des valeurs suivantes :

    • La réservation existe dans votre projet : RESERVATION_NAME

    • La réservation existe dans un autre projet et votre projet peut l'utiliser : projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME

  • YOUR_REGION : région dans laquelle vous souhaitez créer votre cluster GKE. Vous ne pouvez créer le cluster que dans la région où se trouve votre réservation.

  • YOUR_CLUSTER_NAME : nom du cluster GKE à créer.

  • YOUR_BUCKET_NAME : nom du bucket Cloud Storage régional à créer.

  • YOUR_HF_TOKEN : jeton d'accès Hugging Face que vous avez créé dans la section précédente.

  • YOUR_NETWORK_NAME : réseau utilisé par le cluster GKE. Spécifiez une des valeurs suivantes :

    • Si vous avez créé un réseau personnalisé, spécifiez son nom.

    • Sinon, spécifiez default.

  • YOUR_SUBNETWORK_NAME : sous-réseau utilisé par le cluster GKE. Spécifiez une des valeurs suivantes :

    • Si vous avez créé un sous-réseau personnalisé, spécifiez son nom. Vous ne pouvez spécifier qu'un sous-réseau situé dans la même région que la réservation.

    • Sinon, spécifiez default.

Créer un cluster GKE en mode Autopilot

Pour créer un cluster GKE en mode Autopilot, exécutez la commande suivante :

gcloud container clusters create-auto "$CLUSTER_NAME" \
    --project="$PROJECT_ID" \
    --region="$REGION" \
    --release-channel=rapid \
    --network="$NETWORK" \
    --subnetwork="$SUBNETWORK"
La création du cluster GKE peut prendre un certain temps. Pour vérifier que Google Cloud a terminé de créer votre cluster, accédez à Clusters Kubernetes dans la console Google Cloud .

Créer un bucket Cloud Storage

Pour créer un bucket Cloud Storage régional afin de stocker votre modèle, exécutez la commande suivante :

gcloud storage buckets create gs://$GCS_BUCKET_NAME \
    --project=$PROJECT_ID \
    --location=$REGION

Créer un secret Kubernetes pour les identifiants Hugging Face

Pour créer un secret Kubernetes pour les identifiants Hugging Face, procédez comme suit :

  1. Configurez kubectl pour communiquer avec votre cluster GKE :

    gcloud container clusters get-credentials "$CLUSTER_NAME" \
        --location="$REGION" \
        --project="$PROJECT_ID"
  2. Créez un secret Kubernetes pour stocker votre jeton Hugging Face :

    kubectl create secret generic hf-secret \
        --from-literal=hf_token="${HUGGING_FACE_TOKEN}" \
        --dry-run=client -o yaml | kubectl apply -f -

Configurer la fédération d'identité de charge de travail pour Cloud Storage

Pour permettre à GKE d'accéder de manière sécurisée au bucket Cloud Storage, configurez la fédération d'identité de charge de travail GKE :

gcloud iam service-accounts create qwen-gcs-sa \
    --project=$PROJECT_ID

gcloud storage buckets add-iam-policy-binding gs://$GCS_BUCKET_NAME \
    --member="serviceAccount:qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/storage.objectAdmin"

kubectl create serviceaccount qwen-ksa \
    --namespace=default

gcloud iam service-accounts add-iam-policy-binding qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com \
    --project=$PROJECT_ID \
    --role=roles/iam.workloadIdentityUser \
    --member="serviceAccount:$PROJECT_ID.svc.id.goog[default/qwen-ksa]"

kubectl annotate serviceaccount qwen-ksa \
    --namespace=default \
    iam.gke.io/gcp-service-account="qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com"

Remplir le bucket Cloud Storage avec les pondérations du modèle Qwen3

Pour remplir votre bucket Cloud Storage avec les pondérations du modèle Qwen3, exécutez un job Kubernetes qui utilise le pilote CSI Cloud Storage FUSE pour installer votre bucket en tant que volume. La tâche télécharge le modèle depuis Hugging Face s'il n'existe pas déjà dans le bucket.

  1. Créez un fichier nommé qwen3-model-loader.yaml avec le contenu suivant :

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: qwen3-model-loader
    spec:
      template:
        metadata:
          annotations:
            gke-gcsfuse/volumes: "true"
            gke-gcsfuse/cpu-limit: "0"
            gke-gcsfuse/memory-limit: "0"
            gke-gcsfuse/ephemeral-storage-limit: "0"
        spec:
          serviceAccountName: qwen-ksa
          restartPolicy: OnFailure
          containers:
          - name: downloader
            image: python:3.11-slim
            resources:
              requests:
                cpu: "4"
                memory: "16Gi"
                ephemeral-storage: "100Gi"
              limits:
                cpu: "4"
                memory: "16Gi"
                ephemeral-storage: "100Gi"
            command: ["/bin/sh", "-c"]
            args:
            - |
              pip install huggingface_hub
              python3 -c '
              import os
              from huggingface_hub import snapshot_download
              model_id = "Qwen/Qwen3-235B-A22B-Instruct-2507"
              local_dir = "/data/Qwen/Qwen3-235B-A22B-Instruct-2507"
              config_path = os.path.join(local_dir, "config.json")
              if os.path.exists(config_path):
                  print(f"Model already exists at {local_dir}. Skipping download.")
              else:
                  print(f"Downloading model {model_id} to {local_dir}...")
                  snapshot_download(
                      repo_id=model_id,
                      local_dir=local_dir,
                      local_dir_use_symlinks=False,
                      token=os.environ.get("HUGGING_FACE_HUB_TOKEN")
                  )
                  print("Download completed successfully!")
              '
            env:
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_token
            volumeMounts:
            - name: gcs-fuse-volume
              mountPath: /data
          volumes:
          - name: gcs-fuse-volume
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: $GCS_BUCKET_NAME
                mountOptions: "implicit-dirs"
  2. Appliquez le fichier manifeste qwen3-model-loader.yaml pour initialiser le job de téléchargement :

    envsubst < qwen3-model-loader.yaml | kubectl apply -f -
  3. Pour vérifier que le job est en cours d'exécution, diffusez les journaux du job de téléchargement :

    kubectl logs -f job/qwen3-model-loader -c downloader
    
  4. Attendez que la tâche de téléchargement du modèle soit terminée :

    kubectl wait \
        --for=condition=Complete \
        --timeout=1800s job/qwen3-model-loader
  5. Pour supprimer le job, exécutez la commande suivante :

    kubectl delete job qwen3-model-loader --ignore-not-found

Déployer un conteneur vLLM sur votre cluster GKE

Pour déployer le conteneur vLLM afin de diffuser le modèle Qwen3 à l'aide des déploiements Kubernetes, procédez comme suit :

  1. Créez un fichier qwen3-235b-deploy.yaml avec le déploiement vLLM de votre choix :

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-qwen3-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: qwen3-server
      template:
        metadata:
          labels:
            app: qwen3-server
            ai.gke.io/model: Qwen3-235B-A22B-Instruct-2507
            ai.gke.io/inference-server: vllm
            examples.ai.gke.io/source: user-guide
        spec:
          serviceAccountName: qwen-ksa
          containers:
          - name: qwen-inference-server
            image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20250801_0916_RC01
            resources:
              requests:
                cpu: "10"
                memory: "1000Gi"
                ephemeral-storage: "500Gi"
                nvidia.com/gpu: "8"
              limits:
                cpu: "10"
                memory: "1000Gi"
                ephemeral-storage: "500Gi"
                nvidia.com/gpu: "8"
            command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --load-format=runai_streamer
            - --model-loader-extra-config={"distributed":true}
            - --tensor-parallel-size=8
            - --host=0.0.0.0
            - --port=8000
            - --max-model-len=8192
            - --max-num-seqs=4
            - --dtype=bfloat16
            env:
            - name: MODEL_ID
              value: "gs://$GCS_BUCKET_NAME/Qwen/Qwen3-235B-A22B-Instruct-2507"
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            livenessProbe:
              httpGet:
                path: /health
                port: 8000
              initialDelaySeconds: 200
              periodSeconds: 10
            readinessProbe:
              httpGet:
                path: /health
                port: 8000
              initialDelaySeconds: 200
              periodSeconds: 5
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-b200
            cloud.google.com/reservation-name: $RESERVATION_NAME
            cloud.google.com/reservation-affinity: "specific"
            cloud.google.com/gke-gpu-driver-version: latest
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: qwen3-service
    spec:
      selector:
        app: qwen3-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    ---
    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: vllm-qwen3-monitoring
    spec:
      selector:
        matchLabels:
          app: qwen3-server
      endpoints:
      - port: 8000
        path: /metrics
        interval: 30s
  2. Appliquez le fichier qwen3-235b-deploy.yaml à votre cluster GKE :

    envsubst < qwen3-235b-deploy.yaml | kubectl apply -f -
    Comme le conteneur utilise Run:ai Model Streamer pour diffuser les pondérations de modèle directement depuis Cloud Storage, le temps de démarrage est considérablement accéléré.

  3. Pour afficher l'état d'achèvement, exécutez la commande suivante :

    kubectl wait \
        --for=condition=Available \
        --timeout=1800s deployment/vllm-qwen3-deployment
    L'indicateur --timeout=600s permet à la commande de surveiller le déploiement pendant 10 minutes maximum.

Interagir avec Qwen3 à l'aide de curl

Pour vérifier le modèle Qwen3 que vous avez déployé, procédez comme suit :

  1. Configurez le transfert de port vers Qwen3 :

    kubectl port-forward service/qwen3-service 8000:8000
  2. Ouvrez une nouvelle fenêtre de terminal. Vous pouvez ensuite discuter avec votre modèle à l'aide de curl :

    curl http://127.0.0.1:8000/v1/chat/completions \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "model": "Qwen/Qwen3-235B-A22B-Instruct-2507",
      "messages": [
        {
          "role": "user",
          "content": "Describe a GPU in one short sentence?"
        }
      ],
      "stream": false
    }' | jq .
  3. Le résultat ressemble à ce qui suit :

    {
      "id": "chatcmpl-a926ddf7ef2745ca832bda096e867764",
      "object": "chat.completion",
      "created": 1755023619,
      "model": "Qwen/Qwen3-235B-A22B-Instruct-2507",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "A GPU is a specialized electronic circuit designed to rapidly process and render graphics and perform parallel computations.",
            "refusal": null,
            "annotations": null,
            "audio": null,
            "function_call": null,
            "tool_calls": [],
            "reasoning_content": null
          },
          "logprobs": null,
          "finish_reason": "stop",
          "stop_reason": null
        }
      ],
      "service_tier": null,
      "system_fingerprint": null,
      "usage": {
        "prompt_tokens": 16,
        "total_tokens": 36,
        "completion_tokens": 20,
        "prompt_tokens_details": null
      },
      "prompt_logprobs": null,
      "kv_transfer_params": null
    }
    

Observer les performances du modèle

Si vous souhaitez observer les performances de votre modèle, vous pouvez utiliser l'intégration du tableau de bord vLLM dans Cloud Monitoring. Ce tableau de bord vous permet d'afficher les métriques de performances critiques de votre modèle, comme le débit de jetons, la latence réseau et les taux d'erreur. Pour en savoir plus, consultez vLLM dans la documentation de Monitoring.

Effectuer un nettoyage

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Pour éviter que les ressources utilisées dans ce tutoriel soient facturées sur votre compte de facturation Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez chaque ressource individuellement.

Supprimer les ressources

Pour supprimer les ressources du tutoriel, exécutez les commandes suivantes :

envsubst < qwen3-235b-deploy.yaml | kubectl delete -f -
envsubst < qwen3-model-loader.yaml | kubectl delete -f -
kubectl delete secret hf-secret
kubectl delete serviceaccount qwen-ksa

gcloud iam service-accounts delete qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com \
    --project=$PROJECT_ID --quiet

gcloud storage rm --recursive gs://$GCS_BUCKET_NAME

Supprimer votre cluster GKE

Pour supprimer votre cluster GKE, exécutez la commande suivante :

gcloud container clusters delete "$CLUSTER_NAME" \
    --region="$REGION" \
    --project="$PROJECT_ID" \
    --quiet

Supprimer votre projet

Supprimer un projet Google Cloud  :

gcloud projects delete PROJECT_ID

Étapes suivantes