GKE の GPU で vLLM を使用して Mistral Small 4 をサービングする

GPU を使用して vLLM フレームワークで Google Kubernetes Engine(GKE)に Mistral 大規模言語モデル(LLM)をサービングするには、NVIDIA H100 GPU などのサポートされているアクセラレータを使用して GKE クラスタをプロビジョニングする必要があります。

Mistral Small 4 モデルをサービングするには、事前構築済みの vLLM コンテナがモデルの重みを読み込むように構成します。重みは Cloud Storage バケット(--model 引数で指定)から読み込まれます。

重みが読み込まれると、vLLM コンテナは高スループット推論用の OpenAI 互換 API エンドポイントを公開します。

このチュートリアルは、ML エンジニア、プラットフォームの管理者とオペレーターのほか、Kubernetes のコンテナ オーケストレーション機能を使用して H100 GPU ハードウェアで AI/ML ワークロードをサービングすることに関心があるデータと AI のスペシャリストを対象としています。

このページを読む前に、次のことをよく理解しておいてください。

目標

これにより、マネージド Kubernetes 環境における推論用 LLM の実用的なデプロイに関する基礎を学ぶことができます。

  1. Autopilot モードの GKE クラスタで環境を準備する。
  2. vLLM コンテナをクラスタにデプロイする。
  3. vLLM を使用して、curl インターフェースを介して Mistral モデルをサービングする。

始める前に

  • In the Cloud de Confiance console, on the project selector page, select or create a Cloud de Confiance 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

  • Verify that billing is enabled for your Cloud de Confiance project.

  • Enable the required API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  • プロジェクトで次のロール(複数の場合あり)が割り当てられていることを確認します。 roles/container.admin、roles/iam.serviceAccountAdmin

    ロールを確認する

    1. コンソールで、[IAM] ページに移動します。 Cloud de Confiance

      IAM に移動
    2. プロジェクトを選択します。
    3. [Principal] 列で、自分または自分が所属するグループの行をすべて確認します。所属するグループについては、管理者にお問い合わせください。

    4. 自分のメールアドレスを含む行の [**ロール**] 列で、ロールのリストに必要なロールが含まれているかどうか確認します。

    ロールを付与する

    1. コンソールで、[IAM] ページに移動します。 Cloud de Confiance

      IAM に移動
    2. プロジェクトを選択します。
    3. [Grant access] をクリックします。
    4. [新しいプリンシパル] フィールドに、ユーザー ID を入力します。 これは通常、Workforce Identity プール内のユーザーの ID です。詳細については、 IAM ポリシーで Workforce プールユーザーを表すをご覧いただくか、管理者にお問い合わせください。

    5. [**ロールを選択**] をクリックし、ロールを検索します。
    6. 追加のロールを付与するには、 [Add another role] をクリックして各ロールを追加します。
    7. [保存] をクリックします。

環境を準備する

このチュートリアルでは、kubectlgcloud CLI を使用して Cloud de Confiance by S3NSでホストされているリソースを管理します。gcloud CLI で承認して にアクセスできます Cloud de Confiance by S3NS。

gcloud CLI で環境を設定するには、gcloud CLI でデフォルトの環境変数を設定します。

gcloud config set project PROJECT_ID
gcloud config set billing/quota_project PROJECT_ID
export PROJECT_ID=$(gcloud config get project)
export REGION=u-france-east1
export CLUSTER_NAME=CLUSTER_NAME
export GSA_NAME=GSA_NAME
export KSA_NAME=KSA_NAME
export NAMESPACE=NAMESPACE
export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)")
export MODEL_BUCKET_NAME=MODEL_BUCKET_NAME

次の値を置き換えます。

  • PROJECT_ID: の Cloud de Confiance プロジェクト ID
  • REGION: H100 GPU をサポートする u-france-east1 リージョン。どのリージョンでどの GPU を使用できるかを確認できます。
  • CLUSTER_NAME: クラスタの名前。
  • GSA_NAME: Google サービス アカウントの名前(例: mistral-small-gsa)。
  • KSA_NAME: Kubernetes ServiceAccount の名前(例: mistral-small-ksa)。
  • NAMESPACE: Kubernetes Namespace(例: default)。
  • MODEL_BUCKET_NAME: モデルの重みが保存される Cloud Storage バケットの名前。選択したモデルと同じ名前(mistral-small-4-119b-weights など)にできます。

リソースを作成して構成する Cloud de Confiance

次の手順で、必要なリソースを作成します。

GKE クラスタとノードプールを作成する

GKE Autopilot クラスタの GPU で Mistral を提供できます。Autopilot クラスタは、フルマネージドの Kubernetes エクスペリエンスを提供します。

gcloud CLI で次のコマンドを実行します。

gcloud container clusters create-auto CLUSTER_NAME \
    --project=PROJECT_ID \
    --location=REGION \
    --release-channel=rapid

次の値を置き換えます。

  • PROJECT_ID: の Cloud de Confiance プロジェクト ID
  • CLUSTER_NAME: クラスタの名前。
  • REGION: クラスタが配置されているリージョン。

GKE は、デプロイされたワークロードからのリクエストに応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。

Cloud Storage バケットを作成する

  1. gcloud CLI で次のコマンドを実行します。

    gcloud storage buckets create gs://${MODEL_BUCKET_NAME} \
      --project=${PROJECT_ID} \
      --location=${REGION} \
      --uniform-bucket-level-access
    

    これにより、Hugging Face からダウンロードしたモデルファイルを格納する Cloud Storage バケットが作成されます。

  2. モデルの重みをダウンロードしてアップロードします。

    サービングするバージョンの Mistral Small 4 モデルの重みを取得する必要があります(Hugging Face やその他の公式ソースなど)。ダウンロードしたファイルをローカルでディレクトリに整理します。次に例を示します。

    • ./mistral-small-4-119b-weights-local/(Mistral Small 4 モデルのすべてのファイルを含む)

    これらのディレクトリを、デプロイ マニフェストで想定される特定の接頭辞を使用して Cloud Storage バケットにアップロードします。

    # Upload files for the mistral-small-4 model
    gcloud storage cp --recursive ./mistral-small-4-119b-weights-local/* gs://${MODEL_BUCKET_NAME}
    

    このコマンド構造により、モデルファイルは gs://${MODEL_BUCKET_NAME}/config.json などのパスに配置されます。

Cloud Storage アクセス用に GKE の Workload Identity 連携を構成する

モデルの重みを含む Cloud Storage バケットに Kubernetes Pod が安全にアクセスできるようにするには、GKE の Workload Identity Federation for GKE を構成します。

  1. Google サービス アカウント(GSA)を作成します。

    gcloud iam service-accounts create ${GSA_NAME} \
      --project=${PROJECT_ID}
    
  2. GSA のメールアドレスを特定してエクスポートします。

    メール形式は、${PROJECT_ID} がドメイン スコープ(コロンを含む)かどうかによって異なります。

    if [[ $PROJECT_ID == *:* ]]; then
      DOMAIN=$(echo $PROJECT_ID | cut -d: -f1)
      PROJ_NAME=$(echo $PROJECT_ID | cut -d: -f2)
      export GSA_EMAIL="${GSA_NAME}@${PROJ_NAME}.${DOMAIN}.s3ns.iam.gserviceaccount.com"
    else
      export GSA_EMAIL="${GSA_NAME}@${PROJECT_ID}.s3ns.iam.gserviceaccount.com"
    fi
      echo "Using GSA Email: ${GSA_EMAIL}"
    
  3. Kubernetes サービス アカウント(KSA)を作成します。

    この KSA はデプロイ マニフェストで使用されます。

    kubectl create serviceaccount ${KSA_NAME} --namespace ${NAMESPACE}
    

    次のコマンドを実行して作成を確認します。

    kubectl get serviceaccounts --namespace ${NAMESPACE}
    
  4. KSA にアノテーションを付けて、GSA にリンクします。

    このアノテーションは、KSA が権限を借用できる GSA を GKE に通知します。

    kubectl annotate serviceaccount ${KSA_NAME} \
      --namespace ${NAMESPACE} \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    
  5. GSA の権限を借用する権限を KSA に付与します。

    GSA のこの IAM バインディングにより、KSA は GSA として動作できます。

    if [[ $PROJECT_ID == *:* ]]; then
      DOMAIN=$(echo $PROJECT_ID | cut -d: -f1)
      PROJ_NAME=$(echo $PROJECT_ID | cut -d: -f2)
      export WI_MEMBER="serviceAccount:${PROJ_NAME}.${DOMAIN}.s3ns.svc.id.goog[${NAMESPACE}/${KSA_NAME}]"
    else
      export WI_MEMBER="serviceAccount:${PROJECT_ID}.s3ns.svc.id.goog[${NAMESPACE}/${KSA_NAME}]"
    fi
    
    gcloud iam service-accounts add-iam-policy-binding ${GSA_EMAIL} \
      --role roles/iam.workloadIdentityUser \
      --member="${WI_MEMBER}" \
      --project=${PROJECT_ID}
    
  6. バケットから読み取る権限を GSA に付与します。

    バケットに対する storage.objectViewer ロールを GSA に付与します。

    gcloud storage buckets add-iam-policy-binding gs://${MODEL_BUCKET_NAME} \
      --member="serviceAccount:${GSA_EMAIL}" \
      --role="roles/storage.objectViewer" \
      --project=${PROJECT_ID}
    

vLLM に Mistral Small 4 モデルをデプロイする

Mistral Small 4 モデルをデプロイするには、モデルの重みを保存するモデルごとに Cloud Storage バケットを作成し、選択したモデルサイズの Kubernetes Deployment マニフェストを適用します。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。

手順

このマニフェストを適用すると、vLLM コンテナ イメージが pull され、NVIDIA GPU がリクエストされ、 Cloud Storage バケットからモデルの重みに自動的に接続して vLLM 推論エンジンが起動します。

Mistral Small 4

次の手順に沿って、Mistral Small 4 指示用にチューニングされたモデルをデプロイします。

  1. 次の vllm-mistral-small.yaml マニフェストを作成します。

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: a3-edgegpu-8g-nolssd
    spec:
      priorities:
      - machineType: a3-edgegpu-8g-nolssd
        gpu:
          count: 8
          type: nvidia-h100-80gb
      nodePoolAutoCreation:
        enabled: true
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-mistral-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: mistral-server
      template:
        metadata:
          labels:
            app: mistral-server
            ai.gke.io/model: mistral-small-4-119b-weights
            ai.gke.io/inference-server: vllm
            examples.ai.gke.io/source: user-guide
        spec:
          containers:
          - name: inference-server
            image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:gemma4
            resources:
              requests:
                cpu: "48"
                memory: "200Gi"
                ephemeral-storage: "250Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "48"
                memory: "200Gi"
                ephemeral-storage: "250Gi"
                nvidia.com/gpu: "2"
            command: ["./entrypoint.sh"] # Use the image's entrypoint
            args:
            - "python"
            - "-m"
            - "vllm.entrypoints.api_server"
            - "--host=0.0.0.0"
            - "--port=8080"
            - "--model=gs://mistral-small-4-119b-weights" # YOUR Cloud Storage PATH
            - "--tensor-parallel-size=2"
            - "--enable-log-requests"
            - "--enable-chunked-prefill"
            - "--enable-prefix-caching"
            - "--enable-auto-tool-choice"
            - "--generation-config=auto"
            - "--tool-call-parser=mistral"
            - "--dtype=bfloat16"
            - "--max-num-seqs=256"
            - "--max-model-len=8192"
            - "--gpu-memory-utilization=0.90"
            - "--reasoning-parser=mistral"
            - "--trust-remote-code"
            ports:
            - containerPort: 8080
            env:
            - name: GOOGLE_CLOUD_UNIVERSE_DOMAIN
              value: ""
            - name: CLOUDSDK_CORE_UNIVERSE_DOMAIN
              value: ""
            - name: GCS_URI_ARG_KEY
              value: "model"
            - name: GCS_URI_ENV_KEY
              value: "AIP_STORAGE_URI"
            - name: LORA_ADAPTER_ARG_KEY
              value: "lora-modules"
            - name: HF_HUB_ENABLE_HF_TRANSFER
              value: "1"
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/compute-class: a3-edgegpu-8g-nolssd
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: mistral-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8080
          targetPort: 8080
    
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f vllm-mistral-small.yaml
    

    必要に応じて、vLLM オプション --max-model-len=16384 を使用してコンテキスト ウィンドウのサイズを 16K に制限できます。 コンテキスト ウィンドウのサイズを大きくする場合(最大 128K)は、マニフェストとノードプールの構成を調整して GPU 容量を増やします。

検証

  1. Deployment が利用可能になるまで待ちます。

    kubectl wait --for=condition=Available --timeout=1800s deployment/vllm-mistral-deployment
    
  2. 実行中の Deployment のログを表示します。

    kubectl logs -f -l app=mistral-server
    

    Deployment リソースによって Mistral Small 4 モデルデータがダウンロードされます。この処理には数分かかることがあります。出力は次のようになります。

      ...
      ...
      (APIServer pid=1) INFO:     Started server process [1]
      (APIServer pid=1) INFO:     Waiting for application startup.
      (APIServer pid=1) INFO:     Application startup complete.
    

デプロイが利用可能になったら、ポート転送を設定します モデルを操作するための。

モデルをサービングする

このセクションでは、モデルを操作します。モデルが完全にダウンロードされたことを確認してから、次のステップに進んでください。

ポート転送をセットアップする

次のコマンドを実行して、モデルへのポート転送を設定します。

kubectl port-forward svc/llm-service 8080:8080 --namespace default &

出力は次のようになります。

Forwarding from 127.0.0.1:8080 -> 8080

curl を使用してモデルを操作する

このセクションでは、基本的なスモークテストを実行して、デプロイされた Mistral 指示調整済みモデルを確認する方法について説明します。 他のモデルの場合は、mistral-small-4-119b-weights をモデル名に置き換えます。

この例では、テキストのみの入力で Mistral 指示調整済みモデルをテストする方法を示します。

新しいターミナル セッションで、curl を使用してモデルとチャットします。

curl http://127.0.0.1:8080/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mistralai/Mistral-Small-4-119B-2603-eagle",
    "prompt": "What is the capital of France?",
    "max_tokens": 50,
    "temperature": 0.7
  }'

出力は次のようになります。

{
  "id": "cmpl-b5d649b6a2d7a330",
  "object": "text_completion",
  "created": 1781137490,
  "model": "openapi",
  "choices": [
    {
      "index": 0,
      "text": " This question is likely to have been asked millions of times, 
      and the answer is always the same: Paris. But why is Paris the capital 
      of France? The answer to this question is not as simple as 
      it may seem, as it involves a complex",
      "logprobs": null,
      "finish_reason": "length",
      "stop_reason": null,
      "token_ids": null,
      "prompt_logprobs": null,
      "prompt_token_ids": null
    }
  ],
  "service_tier": null,
  "system_fingerprint": null,
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 58,
    "completion_tokens": 50,
    "prompt_tokens_details": null
  },
  "kv_transfer_params": null
}

問題のトラブルシューティング

  • Empty reply from server というメッセージが表示された場合は、コンテナがモデルデータのダウンロードを完了していない可能性があります。モデルがサービス提供の準備ができていることを示す Connected というメッセージがないか、再度 Pod のログを確認します。
  • Connection refused が表示された場合は、ポート転送が有効であることを確認します。

モデルのパフォーマンスをモニタリングする

モデルのオブザーバビリティ指標のダッシュボードを表示する手順は次のとおりです。

  1. Cloud de Confiance コンソールで、[デプロイされるモデル] ページに移動します。

    [デプロイされたモデル] に移動

  2. 特定のデプロイの詳細(指標、ログ、ダッシュボードなど)を表示するには、リスト内のモデル名をクリックします。

  3. モデルの詳細ページで、[オブザーバビリティ] タブをクリックして、次のダッシュボードを表示します。プロンプトが表示されたら、[有効にする] をクリックして、クラスタの指標収集を有効にします。

    • [インフラストラクチャの使用量] ダッシュボードには、使用率の指標が表示されます。
    • [DCGM] ダッシュボードには、DCGM 指標が表示されます。
    • vLLM を使用している場合は、[モデルのパフォーマンス] ダッシュボードが使用可能になり、vLLM モデルのパフォーマンスの指標が表示されます。

Cloud Monitoring の vLLM ダッシュボード統合で指標を表示することもできます。これらの指標は、事前設定されたフィルタを使用することなくすべての vLLM デプロイで集計されます。

vLLM はデフォルトで Prometheus 形式の指標を公開するため、追加のエクスポーターをインストールする必要はありません。 Google Cloud Managed Service for Prometheus を使用してモデルから指標を収集する方法については、Cloud Monitoring のドキュメントで vLLM のオブザーバビリティ ガイダンスをご覧ください。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

デプロイされたリソースを削除する

このガイドで作成したリソースについて Cloud de Confiance アカウントに課金されないようにするには、次のコマンドを実行します。

gcloud container clusters delete CLUSTER_NAME \
    --location=REGION

次の値を置き換えます。

  • REGION: クラスタのリージョン。
  • CLUSTER_NAME: クラスタの名前。

次のステップ