このチュートリアルでは、vLLM サービング フレームワークを使用して、Google Kubernetes Engine(GKE)で Tensor Processing Unit(TPU)を使用して大規模言語モデル(LLM)を提供する方法について説明します。このチュートリアルでは、Llama 3.1 70b を提供し、TPU Trillium(v6e)を使用し、vLLM サーバー指標を使用して水平 Pod 自動スケーリングを設定します。
このドキュメントは、AI/ML ワークロードをデプロイして提供する際に、マネージド Kubernetes での詳細な制御、スケーラビリティ、復元力、ポータビリティ、費用対効果が求められる場合の出発点として適しています。
背景
GKE で TPU v6e を使用すると、効率的なスケーラビリティや高可用性をはじめとするマネージド Kubernetes のメリットをすべて活用して、本番環境に対応した堅牢なサービング ソリューションを実装できます。このセクションでは、このガイドで使用されている重要なテクノロジーについて説明します。
TPU Trillium(v6e)
TPU は、Google が独自に開発した特定用途向け集積回路(ASIC)です。TPU は、TensorFlow、PyTorch、JAX などのフレームワークを使用して構築された ML モデルと AI モデルを高速化するために使用されます。このチュートリアルでは、Google の最新の AI アクセラレータである TPU v6e を使用します。
GKE で TPU を使用する前に、次の学習プログラムを完了することをおすすめします。
- TPU v6e のシステム アーキテクチャについて学習する。
- GKE の TPU についてを確認する。
vLLM
vLLM は、LLM を提供する高度に最適化されたオープンソース フレームワークです。vLLM は、次のような機能により GPU のサービング スループットを向上させることができます。
- PagedAttention による Transformer の実装の最適化。
- サービング スループットを全体的に向上させる連続的なバッチ処理。
- 複数の TPU でのテンソル並列処理と分散サービング。
詳細については、vLLM のドキュメントをご覧ください。
Cloud Storage FUSE
Cloud Storage FUSE は、オブジェクト ストレージ バケットに存在するモデルの重みについて、GKE クラスタから Cloud Storage へのアクセスを提供します。このチュートリアルでは、作成された Cloud Storage バケットは最初は空になります。vLLM が起動すると、GKE は Hugging Face からモデルをダウンロードし、重みを Cloud Storage バケットにキャッシュに保存します。Pod の再起動またはデプロイのスケールアップ時に、後続のモデル読み込みでキャッシュに保存されたデータが Cloud Storage バケットからダウンロードされ、並列ダウンロードを利用してパフォーマンスが最適化されます。
詳細については、Cloud Storage FUSE CSI ドライバのドキュメントをご覧ください。
目標
このチュートリアルは、LLM を提供するために GKE オーケストレーション機能を使用する MLOps または DevOps エンジニア、またはプラットフォーム管理者を対象としています。
このチュートリアルでは、次の手順について説明します。
- モデルの特性に基づいて推奨される TPU v6e トポロジを持つ GKE クラスタを作成します。
- クラスタ内のノードプールに vLLM フレームワークをデプロイします。
- vLLM フレームワークを使用して、ロードバランサを使用して Llama 3.1 70b をサービングする。
- vLLM サーバー指標を使用して水平 Pod 自動スケーリングを設定します。
- モデルをサービングする。
始める前に
- 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.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the required API.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the required API.
-
Make sure that you have the following role or roles on the project:
roles/container.admin
,roles/iam.serviceAccountAdmin
,roles/iam.securityAdmin
,roles/artifactregistry.writer
,roles/container.clusterAdmin
Check for the roles
-
In the Google Cloud console, go to the IAM page.
Go to IAM - Select the project.
-
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.
- For all rows that specify or include you, check the Role colunn to see whether the list of roles includes the required roles.
Grant the roles
-
In the Google Cloud console, go to the IAM page.
[IAM] に移動 - プロジェクトを選択します。
- [ アクセスを許可] をクリックします。
-
[新しいプリンシパル] フィールドに、ユーザー ID を入力します。 これは通常、Google アカウントのメールアドレスです。
- [ロールを選択] リストでロールを選択します。
- 追加のロールを付与するには、 [別のロールを追加] をクリックして各ロールを追加します。
- [保存] をクリックします。
-
- Hugging Face アカウントを作成します(まだ作成していない場合)。
- GKE の Cloud TPU 用にプロジェクトに十分な割り当てがあることを確認します。
環境を準備する
このセクションでは、vLLM とモデルのデプロイに必要なリソースをプロビジョニングします。
モデルへのアクセス権を取得する
Hugging Face リポジトリの Llama 3.1 70b を使用するには、同意契約に署名する必要があります。
アクセス トークンを生成する
Hugging Face トークンをまだ生成していない場合は、新しいトークンを生成します。
- [Your Profile] > [Settings] > [Access Tokens] の順にクリックします。
- [New Token] を選択します。
- 任意の名前と、少なくとも
Read
ロールを指定します。 - [Generate a token] を選択します。
Cloud Shell を起動する
このチュートリアルでは、Cloud Shell を使用して Google Cloud でホストされるリソースを管理します。Cloud Shell には、このチュートリアルに必要な kubectl
や gcloud CLI などのソフトウェアがプリインストールされています。
Cloud Shell を使用して環境を設定するには、次の操作を行います。
Google Cloud コンソールで、Google Cloud コンソールの [Cloud Shell をアクティブにする] をクリックして、Cloud Shell セッションを起動します。これにより、Google Cloud コンソールの下部ペインでセッションが起動します。
デフォルトの環境変数を設定します。
gcloud config set project PROJECT_ID && \ export PROJECT_ID=$(gcloud config get project) && \ export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") && \ export CLUSTER_NAME=CLUSTER_NAME && \ export ZONE=ZONE && \ export HF_TOKEN=HUGGING_FACE_TOKEN && \ export CLUSTER_VERSION=CLUSTER_VERSION && \ export GSBUCKET=GSBUCKET && \ export KSA_NAME=KSA_NAME && \ export NAMESPACE=NAMESPACE
次の値を置き換えます。
- PROJECT_ID: Google Cloud のプロジェクト ID。
- CLUSTER_NAME: GKE クラスタの名前。
- ZONE: v6e TPU をサポートするゾーン。
- CLUSTER_VERSION: GKE バージョン。使用するマシンタイプをサポートしている必要があります。デフォルトの GKE バージョンは、ターゲット TPU で利用できない場合があります。TPU v6e は、GKE バージョン 1.31.2-gke.1115000 以降でサポートされています。
- GSBUCKET: Cloud Storage FUSE に使用する Cloud Storage バケットの名前。
- KSA_NAME: Cloud Storage バケットへのアクセスに使用される Kubernetes ServiceAccount の名前。Cloud Storage FUSE を機能させるには、バケットへのアクセス権が必要です。
- NAMESPACE: vLLM アセットをデプロイする Kubernetes Namespace。
GKE クラスタを作成する
GKE Autopilot クラスタまたは GKE Standard クラスタの TPU で LLM を提供できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。
Autopilot
GKE Autopilot クラスタを作成します。
gcloud container clusters create-auto CLUSTER_NAME \ --cluster-version=CLUSTER_VERSION \ --release-channel=rapid
PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。
スタンダード
GKE Standard クラスタを作成します。
gcloud container clusters create CLUSTER_NAME \ --project=PROJECT_ID \ --zone=ZONE \ --cluster-version=CLUSTER_VERSION \ --release-channel=rapid \ --workload-pool=PROJECT_ID.svc.id.goog \ --addons GcsFuseCsiDriver
TPU スライス ノードプールを作成します。
gcloud container node-pools create tpunodepool \ --zone=ZONE \ --num-nodes=1 \ --machine-type=ct6e-standard-8t \ --cluster=CLUSTER_NAME \ --enable-autoscaling --total-min-nodes=1 --total-max-nodes=2
GKE は、LLM 用に次のリソースを作成します。
- GKE 用 Workload Identity 連携を使用し、Cloud Storage FUSE CSI ドライバが有効になっている GKE Standard クラスタ。
ct6e-standard-8t
マシンタイプの TPU v6e ノードプール。このノードプールには 1 つのノード、8 個の TPU チップがあり、自動スケーリングが有効になっています。
クラスタと通信するように kubectl を設定する
クラスタと通信するように kubectl を構成するには、次のコマンドを実行します。
gcloud container clusters get-credentials CLUSTER_NAME --location=ZONE
Hugging Face の認証情報用の Kubernetes Secret を作成する
Namespace を作成します。
default
Namespace を使用している場合は、この手順をスキップできます。kubectl create namespace NAMESPACE
Hugging Face トークンを含む Kubernetes Secret を作成するには、次のコマンドを実行します。
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=HUGGING_FACE_TOKEN \ --namespace NAMESPACE
Cloud Storage バケットを作成する
Cloud Shell で、次のコマンドを実行します。
gcloud storage buckets create gs://GSBUCKET \
--uniform-bucket-level-access
これにより、Hugging Face からダウンロードしたモデルファイルを格納する Cloud Storage バケットが作成されます。
バケットにアクセスする Kubernetes ServiceAccount を設定する
Kubernetes ServiceAccount を作成します。
kubectl create serviceaccount KSA_NAME --namespace NAMESPACE
Cloud Storage バケットにアクセスできるように、Kubernetes ServiceAccount に読み取り / 書き込みアクセス権を付与します。
gcloud storage buckets add-iam-policy-binding gs://GSBUCKET \ --member "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \ --role "roles/storage.objectUser"
または、プロジェクト内のすべての Cloud Storage バケットに対する読み取り / 書き込みアクセス権を付与することもできます。
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME" \ --role "roles/storage.objectUser"
GKE は、LLM 用に次のリソースを作成します。
- ダウンロードしたモデルとコンパイル キャッシュを保存する Cloud Storage バケット。Cloud Storage FUSE CSI ドライバがバケットのコンテンツを読み取ります。
- ファイル キャッシュが有効になっているボリュームと、Cloud Storage FUSE の並列ダウンロード機能。
ベスト プラクティス: モデル コンテンツ(重みファイルなど)の予想サイズに応じて、
tmpfs
またはHyperdisk / Persistent Disk
を基盤とするファイル キャッシュを使用します。このチュートリアルでは、RAM を基盤とする Cloud Storage FUSE ファイル キャッシュを使用します。
TPU イメージをビルドしてデプロイする
vLLM サーバーをコンテナ化します。
vLLM リポジトリのクローンを作成してイメージをビルドします。
git clone https://github.com/vllm-project/vllm && cd vllm && git reset --hard cd34029e91ad2d38a58d190331a65f9096c0b157 && docker build -f Dockerfile.tpu . -t vllm-tpu
イメージを Artifact Registry に push します。
gcloud artifacts repositories create vllm-tpu --repository-format=docker --location=REGION_NAME && \ gcloud auth configure-docker REGION_NAME-docker.pkg.dev && \ docker image tag vllm-tpu REGION_NAME-docker.pkg.dev/PROJECT_ID/vllm-tpu/vllm-tpu:latest && \ docker push REGION_NAME-docker.pkg.dev/PROJECT_ID/vllm-tpu/vllm-tpu:latest
vLLM モデルサーバーをデプロイする
vLLM モデルサーバーをデプロイする手順は次のとおりです。
vllm-llama3-70b.yaml
として保存した Deployment マニフェストを調べます。Deployment は、クラスタ内のノード間で Pod の複数のレプリカを実行できる Kubernetes API です。次のコマンドを実行してマニフェストを適用します。
kubectl apply -f vllm-llama3-70b.yaml -n NAMESPACE
実行中のモデルサーバーのログを表示します。
kubectl logs -f -l app=vllm-tpu -n NAMESPACE
出力は次のようになります。
INFO 09-20 19:03:48 launcher.py:19] Available routes are: INFO 09-20 19:03:48 launcher.py:27] Route: /openapi.json, Methods: GET, HEAD INFO 09-20 19:03:48 launcher.py:27] Route: /docs, Methods: GET, HEAD INFO 09-20 19:03:48 launcher.py:27] Route: /docs/oauth2-redirect, Methods: GET, HEAD INFO 09-20 19:03:48 launcher.py:27] Route: /redoc, Methods: GET, HEAD INFO 09-20 19:03:48 launcher.py:27] Route: /health, Methods: GET INFO 09-20 19:03:48 launcher.py:27] Route: /tokenize, Methods: POST INFO 09-20 19:03:48 launcher.py:27] Route: /detokenize, Methods: POST INFO 09-20 19:03:48 launcher.py:27] Route: /v1/models, Methods: GET INFO 09-20 19:03:48 launcher.py:27] Route: /version, Methods: GET INFO 09-20 19:03:48 launcher.py:27] Route: /v1/chat/completions, Methods: POST INFO 09-20 19:03:48 launcher.py:27] Route: /v1/completions, Methods: POST INFO 09-20 19:03:48 launcher.py:27] Route: /v1/embeddings, Methods: POST INFO: Started server process [1] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) (RayWorkerWrapper pid=25987) INFO 09-20 19:03:46 tpu_model_runner.py:290] Compilation for decode done in 202.93 s. (RayWorkerWrapper pid=25987) INFO 09-20 19:03:46 tpu_model_runner.py:283] batch_size: 256, seq_len: 1 [repeated 7x across cluster] INFO 09-20 19:03:53 metrics.py:351] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.0%, CPU KV cache usage: 0.0%.
モデルをサービングする
次のコマンドを実行して、Service の外部 IP アドレスを取得します。
export vllm_service=$(kubectl get service vllm-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
新しいターミナルで、
curl
を使用してモデルを操作します。curl http://$vllm_service:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Meta-Llama-3.1-70B", "prompt": "San Francisco is a", "max_tokens": 7, "temperature": 0 }'
出力例を以下に示します。
{"id":"cmpl-6b4bb29482494ab88408d537da1e608f","object":"text_completion","created":1727822657,"model":"meta-llama/Meta-Llama-3-8B","choices":[{"index":0,"text":" top holiday destination featuring scenic beauty and","logprobs":null,"finish_reason":"length","stop_reason":null,"prompt_logprobs":null}],"usage":{"prompt_tokens":5,"total_tokens":12,"completion_tokens":7}}
カスタム オートスケーラーを設定する
このセクションでは、カスタム Prometheus 指標を使用して水平 Pod 自動スケーリングを設定します。vLLM サーバーから Google Cloud Managed Service for Prometheus の指標を使用します。
詳細については、Google Cloud Managed Service for Prometheus をご覧ください。これは GKE クラスタでデフォルトで有効になっています。
クラスタにカスタム指標 Stackdriver アダプタを設定します。
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
カスタム指標 Stackdriver アダプタが使用するサービス アカウントに Monitoring 閲覧者のロールを追加します。
gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter
次のマニフェストを
vllm_pod_monitor.yaml
として保存します。クラスタに適用します。
kubectl apply -f vllm_pod_monitor.yaml
vLLM エンドポイントに負荷を生成する
vLLM サーバーに負荷を作成して、GKE がカスタム vLLM 指標で自動スケーリングする方法を確認します。
bash スクリプト(
load.sh
)を実行して、N
個の並列リクエストを vLLM エンドポイントに送信します。#!/bin/bash N=PARALLEL_PROCESSES export vllm_service=$(kubectl get service vllm-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}') for i in $(seq 1 $N); do while true; do curl http://$vllm_service:8000/v1/completions -H "Content-Type: application/json" -d '{"model": "meta-llama/Meta-Llama-3.1-70B", "prompt": "Write a story about san francisco", "max_tokens": 100, "temperature": 0}' done & # Run in the background done wait
PARALLEL_PROCESSES は、実行する並列プロセスの数に置き換えます。
bash スクリプトを実行します。
nohup ./load.sh &
Google Cloud Managed Service for Prometheus が指標を取り込むことを確認する
Google Cloud Managed Service for Prometheus が指標をスクレイピングし、vLLM エンドポイントに負荷を追加すると、Cloud Monitoring で指標を表示できます。
Google Cloud コンソールで、[Metrics Explorer] ページに移動します。
[< > PromQL] をクリックします。
次のクエリを入力して、トラフィック指標を確認します。
vllm:avg_generation_throughput_toks_per_s{cluster='CLUSTER_NAME_HERE'}
折れ線グラフでは、vLLM 指標は 0(プリロード)から値(ポストロード)にスケールアップします。このグラフは、vLLM 指標が Google Cloud Managed Service for Prometheus に取り込まれていることを確認します。
次の画像は、読み込みスクリプトの実行後のグラフの例です。この場合、モデルサーバーは 1 秒あたり約 2,000 個の生成トークンを処理しています。
HorizontalPodAutoscaler 構成をデプロイする
このセクションでは、Horizontal Pod Autoscaler 構成をデプロイします。
次のマニフェストを
vllm-hpa.yaml
として保存します。Google Cloud Managed Service for Prometheus の vLLM 指標は
vllm:metric_name
形式に従います。ベスト プラクティス: スループットをスケーリングするには、
num_requests_waiting
を使用します。レイテンシに敏感な TPU のユースケースにはgpu_cache_usage_perc
を使用します。HorizontalPodAutoscaler 構成をデプロイします。
kubectl apply -f vllm-hpa.yaml
GKE は、デプロイする別の Pod をスケジュールします。これにより、ノードプール オートスケーラーがトリガーされ、2 番目の vLLM レプリカをデプロイする前に 2 番目のノードが追加されます。
Pod の自動スケーリングの進行状況を確認します。
kubectl get hpa --watch
出力は次のようになります。
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE vllm-hpa Deployment/vllm-tpu <unknown>/5 1 2 0 6s vllm-hpa Deployment/vllm-tpu 34972m/5 1 2 1 16s vllm-hpa Deployment/vllm-tpu 25112m/5 1 2 2 31s vllm-hpa Deployment/vllm-tpu 35301m/5 1 2 2 46s vllm-hpa Deployment/vllm-tpu 25098m/5 1 2 2 62s vllm-hpa Deployment/vllm-tpu 35348m/5 1 2 2 77s
10 分待ってから、Google Cloud Managed Service for Prometheus が指標を取り込むことを確認するの手順を繰り返します。Google Cloud Managed Service for Prometheus は、両方の vLLM エンドポイントから指標を取り込みます。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
デプロイされたリソースを削除する
このガイドで作成したリソースについて、Google Cloud アカウントに課金されないようにするには、次のコマンドを実行します。
ps -ef | grep load.sh | awk '{print $2}' | xargs -n1 kill -9
gcloud container clusters delete CLUSTER_NAME \
--location=ZONE
次のステップ
- GKE の TPU の詳細を確認する。
- 詳しくは、Horizontal Pod Autoscaler の設定に使用できる指標をご覧ください。
- vLLM の GitHub リポジトリとドキュメントを確認する。