Distributed Cloud ソフトウェアのみのリファレンス実装でモデル提供を開く

概要

このドキュメントは、ソリューション リファレンス実装(SRI)ガイドとして、Distributed Cloud ソフトウェアのみのオープンモデル サービング ソリューションのデプロイ、サービング、検証に必要な具体的な手順について説明します。

このガイドでは、物理 NVIDIA GPU リソース(RTX PRO 6000 など)を利用して、Distributed Cloud ソフトウェアのみのエッジ デプロイを対象とした単一ノード クラスタ構成で Gemma 4(google/gemma-4-31B-it)を実行する最適化された vLLM サービング エンジンのデプロイを実装します。

このチュートリアルは、Distributed Cloud ソフトウェアのみのクラスタに対する kubectl アクセス権を持つ CLI ターミナル クライアントから実行するように設計されています。

目標

このソリューション リファレンス実装を完了すると、次のことができるようになります。

  • ローカル .env ファイルを使用して、サービング環境パラメータを構成します。
  • local-shared ストレージ クラスを使用して、モデルの重みを永続化する Persistent Volume Claim(PVC)をデプロイします。
  • Vertex AI 認定コンテナを利用して、最適化された vLLM サービング エンジンをデプロイし、物理 nvidia.com/gpu リソースをマッピングします。
  • Gradio ウェブ UI をデプロイして、インタラクティブなチャット インターフェースを提供します。
  • ローカル ポート転送トンネルを確立して、API とウェブ UI を介してサービングの応答性を検証します。
  • Cloud Logging と Cloud Monitoring へのログと指標(GPU テレメトリーを含む)の取り込みを確認して、オブザーバビリティ統合を確認します。

始める前に

前提条件(クラスタ設定)

このガイドでは、GPU サポートが構成された Distributed Cloud ソフトウェアのみのクラスタが実行されていることを前提としています。クラスタのインストールについては、ベアメタル用 Distributed Cloud ソフトウェアのみの公式ドキュメントをご覧ください。GPU 構成は、NVIDIA GPU を設定して使用するの公式 Google Cloudドキュメントに準拠している必要があります。

クライアント ワークステーションの前提条件

ローカル ターミナル環境に次のツールがインストールされ、構成されていることを確認します。

  • gcloud CLI: プロジェクトの構成とログのクエリに必要です。認証(gcloud auth login)され、Distributed Cloud ソフトウェアのみのクラスタが登録されているアクティブなGoogle Cloud プロジェクトに構成されている必要があります。
  • kubectl: クラスタ リソースの管理に必要です。ターゲットの Distributed Cloud ソフトウェアのみのクラスタにアクセスするための適切なコンテキスト(接続ゲートウェイやローカル ネットワークへの直接アクセスなど)で構成する必要があります。
  • curl: サービング エンドポイントにテスト リクエストを送信するために必要です。
  • jq: サービング エンドポイントからの JSON 出力を解析するために必要です。

Hugging Face モデルへのアクセス

Gemma 4 モデルをダウンロードしてデプロイするには、Hugging Face リポジトリへのアクセス権が必要です。

  1. Hugging Face アカウント: Hugging Face に登録済みのアカウントがあることを確認します。
  2. モデルのライセンスに同意する: Gemma 4 31B IT モデルページに移動し、ライセンス条項に同意して、ゲート付きモデルの重みにアクセスします。
  3. アクセス トークンを生成する: Hugging Face アカウント設定([Settings] -> [Access Tokens])から、読み取り権限を持つユーザー アクセス トークンを生成します。このトークンは、構成で HF_TOKEN として使用されます。

中央リファレンス構成

すべてのデプロイ パラメータは、<local-config-dir>/.env にある中央の .env ファイルで管理されます。このファイルが存在し、特定のパラメータ(Hugging Face トークン、名前空間、モデル名など)が含まれていることを確認します。

.env 構造の例:

# GDCso Cluster Namespace
NAMESPACE_NAME="your-custom-namespace"

# Hugging Face Token (Required to download gated Gemma models)
HF_TOKEN="your-hf-token-here"

# Model Sizing Parameters
MODEL_NAME="google/gemma-4-31B-it"
SAFE_MODEL_NAME="google-gemma-4-31B-it"

# Hyperparameters
MAX_MODEL_LEN=8192
GPU_MEMORY_UTILIZATION=0.95
MAX_NUM_SEQS=512
MAX_NUM_BATCHED_TOKENS=4096
DTYPE="bfloat16"

# Pod Sizing Requests
CPU_REQUEST="4"
MEMORY_REQUEST="80"

環境と認証情報を設定する

Namespace と Hugging Face Secret を作成する

デプロイする前に、Namespace と Hugging Face トークン シークレットを作成する必要があります。

# Navigate to your project root
cd <local-working-dir>

# Sourced from your local .env file
source <local-config-dir>/.env

# Create namespace
kubectl create namespace ${NAMESPACE_NAME} --dry-run=client -o yaml | kubectl apply -f -

# Create Hugging Face token secret
kubectl create secret generic hf-token-secret \
  --from-literal=token="${HF_TOKEN}" \
  -n "${NAMESPACE_NAME}" --dry-run=client -o yaml | kubectl apply -f -

Kubernetes での vLLM のデプロイ

このデプロイは、PVC、Service、Deployment の 3 つの主要なマニフェストで構成されています。これらのテンプレートは、デプロイ時に置き換えられる環境変数を使用します。

Persistent Volume Claim(PVC)

PVC は、Distributed Cloud ソフトウェアの local-shared ストレージ クラスのみを使用して、Pod の再起動後もモデルの重みを保持します。

次の内容で vllm-pvc.yaml という名前のファイルを作成します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: model-cache-pvc
  namespace: ${NAMESPACE_NAME}
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-shared
  resources:
    requests:
      storage: 100Gi

サービス

vLLM API サーバーをポート 8000 で内部的に公開します。

次の内容で vllm-service.yaml という名前のファイルを作成します。

apiVersion: v1
kind: Service
metadata:
  name: vllm-service
  namespace: ${NAMESPACE_NAME}
  labels:
    app: vllm
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/path: "/metrics"
    prometheus.io/port: "8000"
spec:
  ports:
    - name: http
      port: 8000
      targetPort: 8000
  selector:
    app: vllm
  type: ClusterIP

デプロイ

vLLM コンテナを実行し、モデル キャッシュ ボリュームをマウントして、物理 GPU リソースをリクエストします。96 GB の VRAM は量子化されていない BF16 重み(約 62 GB)に適合しますが、このリファレンス実装では、Blackwell FP8 量子化(--quantization=fp8、約 31 GB の重み)を有効にして、KV キャッシュを 56.53 GiB(61,728 トークン)に拡張し、同時スループットを向上させます。

次の内容で vllm-deployment.yaml という名前のファイルを作成します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-deployment
  namespace: ${NAMESPACE_NAME}
  labels:
    app: vllm
    ai.gke.io/inference-server: vllm
    ai.gke.io/model: ${SAFE_MODEL_NAME}
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
        examples.ai.gke.io/source: user-guide
        ai.gke.io/inference-server: vllm
        ai.gke.io/model: ${SAFE_MODEL_NAME}
    spec:
      runtimeClassName: nvidia
      containers:
        - name: vllm-container
          image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:gemma4
          imagePullPolicy: IfNotPresent
          command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
          args:
            - --model=$(MODEL_ID)
            - --host=0.0.0.0
            - --port=8000
            - --tensor-parallel-size=1
            - --enable-log-requests
            - --max-model-len=${MAX_MODEL_LEN}
            - --gpu-memory-utilization=${GPU_MEMORY_UTILIZATION}
            - --max-num-seqs=${MAX_NUM_SEQS}
            - --max-num-batched-tokens=${MAX_NUM_BATCHED_TOKENS}
            - --dtype=${DTYPE}
            - --trust-remote-code
            - --enable-prefix-caching
            - --enable-chunked-prefill
            - --quantization=fp8
          env:
            - name: MODEL_ID
              value: ${MODEL_NAME}
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-token-secret
                  key: token
            - name: LD_LIBRARY_PATH
              value: "/usr/local/nvidia/lib64"
          ports:
            - name: http
              containerPort: 8000
          resources:
            requests:
              cpu: ${CPU_REQUEST}
              memory: "${MEMORY_REQUEST}Gi"
              nvidia.com/gpu: "1"
            limits:
              cpu: ${CPU_REQUEST}
              memory: "${MEMORY_REQUEST}Gi"
              nvidia.com/gpu: "1"
          volumeMounts:
            - mountPath: /root/.cache/huggingface
              name: cache-volume
            - mountPath: /dev/shm
              name: dshm
      volumes:
        - name: cache-volume
          persistentVolumeClaim:
            claimName: model-cache-pvc
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: 16Gi

Gradio UI のデプロイ

Gradio UI は、モデルとチャットするためのインタラクティブなウェブ インターフェースを提供します。クラスタ内にデプロイされ、内部 Kubernetes ネットワークを介して vLLM サービスに接続します。

Gradio のデプロイ

次の内容で gradio-deployment.yaml という名前のファイルを作成します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gradio-deployment
  namespace: ${NAMESPACE_NAME}
  labels:
    app: gradio
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gradio
  template:
    metadata:
      labels:
        app: gradio
    spec:
      containers:
      - name: gradio
        image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
        resources:
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        env:
        - name: CONTEXT_PATH
          value: "/v1/chat/completions"
        - name: HOST
          value: "http://vllm-service:8000"
        - name: MODEL_ID
          value: "${MODEL_NAME}"
        ports:
        - containerPort: 7860

Gradio サービス

次の内容で gradio-service.yaml という名前のファイルを作成します。

apiVersion: v1
kind: Service
metadata:
  name: gradio-service
  namespace: ${NAMESPACE_NAME}
spec:
  selector:
    app: gradio
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 7860
  type: ClusterIP

オブザーバビリティの構成

アプリケーションのロギングとモニタリングの構成の詳細については、公式の アプリケーションのロギングとモニタリングのガイドをご覧ください。

vLLM モニタリング

Google Cloud Managed Service for Prometheus(GMP)による vLLM 指標のスクレイピングを有効にするには、vLLM Pod をターゲットとする PodMonitoring リソースをデプロイします。

次の内容で vllm-pod-monitoring.yaml という名前のファイルを作成します。

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: vllm-pod-monitoring
  namespace: ${NAMESPACE_NAME}
spec:
  selector:
    matchLabels:
      app: vllm
  endpoints:
  - port: http
    interval: 30s

GPU モニタリング

Google Cloud Managed Service for Prometheus(GMP)による NVIDIA DCGM エクスポータからの GPU 指標のスクレイピングを有効にするには、gpu-operator Namespace に PodMonitoring リソースをデプロイします。詳細については、GPU 指標を Cloud Monitoring に送信するをご覧ください。

次の内容で gpu-pod-monitoring.yaml という名前のファイルを作成します。

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: dcgm-gmp
  namespace: gpu-operator
spec:
  selector:
    matchLabels:
      app: nvidia-dcgm-exporter
  endpoints:
  - port: metrics
    interval: 30s

実行のステップ

マニフェストのデプロイ

マニフェストをクラスタに適用します。YAML ファイルには環境変数プレースホルダが含まれているため、適用する前に envsubst を使用して .env ファイルの変数を置き換えます。

  1. YAML ファイルを含む作業ディレクトリに移動します。

    cd <local-working-dir>
    
  2. 環境変数を取得します。

    source <local-config-dir>/.env
    
  3. マニフェストを順番に適用します。

    # Apply core serving manifests
    envsubst < vllm-pvc.yaml | kubectl apply -f -
    envsubst < vllm-service.yaml | kubectl apply -f -
    envsubst < vllm-deployment.yaml | kubectl apply -f -
    
    # Apply observability manifests
    envsubst < vllm-pod-monitoring.yaml | kubectl apply -f -
    kubectl apply -f gpu-pod-monitoring.yaml
    
    # Apply Gradio UI manifests
    envsubst < gradio-deployment.yaml | kubectl apply -f -
    envsubst < gradio-service.yaml | kubectl apply -f -
    

検証

Pod の起動シーケンスをモニタリングする

コンテナログをストリーミングして、起動シーケンスを追跡します。

# 1. Check pod status (wait until it is Running)
kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm

# 2. Stream logs to verify model loading
kubectl logs -f -l app=vllm -n ${NAMESPACE_NAME}

ログにアクティブなサービングの準備完了シグナルが表示されるまで待ちます。

INFO: Application startup complete.

ポート転送トンネルを確立する

エンドポイントをローカルでテストするには、サービスポート 8000 を転送します。

kubectl port-forward service/vllm-service 8000:8000 -n ${NAMESPACE_NAME}

このターミナルは開いたままにするか、バックグラウンドで実行します。

クエリ サービング エンドポイント

別のターミナルから、API の応答性をテストします。

1. クエリモデルのリスト

curl -s http://localhost:8000/v1/models | jq

2. チャット補完をクエリする

curl -s http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"${MODEL_NAME}"'",
    "messages": [
      {"role": "user", "content": "What is AGI in 100 words"}
    ],
    "max_tokens": 150
  }' | jq

GPU と VRAM の割り当てを確認する

モデルがハードウェアを効率的に使用し、メモリ フットプリントが正しいことを確認するには、GPU 監査を実行します。

Pod 内の nvidia-smi を介して GPU を監査する

アクティブな vLLM Pod の名前を取得し、コンテナ内で nvidia-smi を実行します。

# Dynamically get the pod name
export VLLM_POD_NAME=$(kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm -o jsonpath='{.items[0].metadata.name}')

# Run nvidia-smi inside the container
kubectl exec ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} -- nvidia-smi

想定される出力: 出力は、GPU_MEMORY_UTILIZATION パラメータと一致する物理 VRAM 使用率を報告します。たとえば、GPU_MEMORY_UTILIZATION=0.95 で google/gemma-4-31B-it を実行する NVIDIA RTX PRO 6000(約 96 GB VRAM)を搭載したワークステーションでは、VLLM::EngineCore に割り当てられた約 95,800 MiB が表示されます。

+-----------------------------------------------------------------------------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA RTX PRO 6000 Blac...    On  |   00000000:05:00.0 Off |                    0 |
| N/A   36C    P0             85W /  600W |   95805MiB /  97887MiB |      0%      Default |
+-----------------------------------------+------------------------+----------------------+

ログで KV キャッシュの割り当てを確認する

vLLM の内部割り当てログを調べて、KV キャッシュのサイズとトークンの同時実行性を確認することもできます。

kubectl logs ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} | grep -E "Available KV cache|GPU KV cache size"

予想される出力:

(EngineCore pid=362) INFO 06-18 15:03:43 [gpu_worker.py:456] Available KV cache memory: 56.53 GiB
(EngineCore pid=362) INFO 06-18 15:03:43 [kv_cache_utils.py:1316] GPU KV cache size: 61,728 tokens

これにより、56.53 GiB の VRAM がコンテキスト KV キャッシュ用に予約され、大量の同時実行トークンが可能になります。

Gradio UI のデプロイを確認する

Gradio Pod が実行されたら、ポート転送トンネルを確立して UI にアクセスできます。

Gradio Pod のステータスをモニタリングする

Gradio Pod が実行されていることを確認します。

kubectl get pods -n ${NAMESPACE_NAME} -l app=gradio

予想される出力:

NAME                                READY   STATUS    RESTARTS   AGE
gradio-deployment-yyyyyyyy-yyyyy    1/1     Running   0          1m

Gradio へのポート転送トンネルを確立する

Gradio サービスのポート 8080 をローカルポート 7860 に転送します。

kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME}

このターミナルを開いたままにするか、バックグラウンドで実行します。

kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME} > pf_gradio.log 2>&1 & sleep 3

ウェブ UI にアクセスする

  • ローカル ワークステーションで実行している場合: ブラウザを開き、http://localhost:7860 に直接移動します。
  • Cloud Shell 内で実行している場合: [ウェブでプレビュー] ボタンを使用して、[ポートを変更] を選択し、7860 と入力して、[変更してプレビュー] をクリックします。

Gradio のチャットボット インターフェースが表示されます。メッセージを入力して Gemma モデルを操作できます。Gradio Pod は、リクエストを内部的に vllm-service エンドポイントに転送します。

トンネルをクリーンアップする

ポート転送トンネルを停止するには:

pkill -f "port-forward service/gradio-service"

モニタリングの確認

vLLM がデプロイされ、PodMonitoring リソースが適用されると、指標が Cloud Monitoring に取り込まれていることを確認できます。

PodMonitoring のステータスを確認する

PodMonitoring リソースが作成され、アクティブであることを確認します。

kubectl get podmonitoring -n ${NAMESPACE_NAME}

Google Cloud コンソールを使用して指標の取り込みを確認する

指標が取り込まれていることを確認するには、 Google Cloud コンソール(Metrics Explorer)を使用します。

  1. Google Cloud コンソールで [Metrics Explorer] を開きます。
    • https://console.cloud.google.com/monitoring/metrics-explorer に移動します(プロジェクト ${GCP_PROJECT_ID} を選択してください)。
  2. [指標を選択] プルダウンで、次の指標を検索して選択します。
    • prometheus.googleapis.com/vllm:num_requests_running/gauge を使用して vLLM 指標を確認します。
    • prometheus.googleapis.com/DCGM_FI_DEV_GPU_UTIL/gauge を使用して GPU 使用率指標を確認します。
  3. グラフを観察して、データポイントがアクティブにプロットされていることを確認します。

ロギングの検証

ワークロードが実行されたら、ログが Cloud Logging にエクスポートされていることを確認できます。

vLLM ログの取り込みを確認する

vLLM コンテナログが Cloud Logging にエクスポートされていることを確認します。

project_id=$(gcloud config get-value project)

gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"${NAMESPACE_NAME}\" AND resource.labels.container_name=\"vllm-container\"" --limit=10 --project=${project_id}

GPU エクスポータのログの取り込みを確認する

GPU エクスポータ コンテナログが Cloud Logging にエクスポートされていることを確認します。

project_id=$(gcloud config get-value project)

gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"gpu-operator\" AND resource.labels.container_name=\"nvidia-dcgm-exporter\"" --limit=10 --project=${project_id}

Google Cloud コンソール(ログ エクスプローラ)を使用してログを確認する

Google Cloud コンソールを使用してログの取り込みを確認することもできます。

  1. Google Cloud コンソールでログ エクスプローラを開きます。
    • https://console.cloud.google.com/logs/query に移動します(プロジェクト ${GCP_PROJECT_ID} を選択してください)。
  2. [クエリ] ボックスに次のクエリを入力して、vLLM ログを表示します。

    resource.type="k8s_container"
    resource.labels.namespace_name="<NAMESPACE_NAME>"
    resource.labels.container_name="vllm-container"
    

    (<NAMESPACE_NAME> は実際の Namespace(your-custom-namespace など)に置き換えます)。

  3. [クエリを実行] をクリックします。vLLM コンテナのログエントリが表示されます。

  4. GPU エクスポータのログを確認するには、次のクエリを実行します。

    resource.type="k8s_container"
    resource.labels.namespace_name="gpu-operator"
    resource.labels.container_name="nvidia-dcgm-exporter"