このチュートリアルでは、効率的でスケーラブルな推論を行うために、Google Kubernetes Engine(GKE)で複数の GPU を使用して、大規模言語モデル(LLM)をサービングする方法について説明します。このチュートリアルでは、複数の L4 GPU を使用する GKE クラスタを作成し、次のいずれかのモデルを処理する GKE インフラストラクチャを準備します。
GPU の数はモデルのデータ形式によって異なります。このチュートリアルでは、各モデルで 2 つの L4 GPU を使用します。詳細については、GPU の量の計算をご覧ください。
GKE でこのチュートリアルを始める前に、GKE での GPU についてをご覧ください。
目標
このチュートリアルは、LLM を提供するために GKE オーケストレーション機能を使用する MLOps または DevOps エンジニア、またはプラットフォーム管理者を対象としています。
このチュートリアルでは、次の手順について説明します。
- クラスタとノードプールを作成する。
- ワークロードを準備する。
- ワークロードをデプロイする。
- LLM インターフェースを操作する。
始める前に
作業を始める前に、次のことを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
モデルによっては追加の要件があります。次の要件を満たしていることを確認してください。
- Hugging Face からモデルにアクセスするには、HuggingFace トークンを使用します。
- Mixtral 8x7b モデルの場合 - Mistral Mixtral モデルの条件に同意します。
- Llama 3 70b モデルの場合 - Meta Llama モデルの有効なライセンスがあることを確認します。
環境を準備する
Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
Cloud Shell を開くデフォルトの環境変数を設定します。
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export REGION=us-central1
PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。
GKE クラスタとノードプールを作成する
GKE Autopilot クラスタまたは GKE Standard クラスタの GPU で LLM を提供できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。
Autopilot
Cloud Shell で、次のコマンドを実行します。
gcloud container clusters create-auto l4-demo \ --project=${PROJECT_ID} \ --region=${REGION} \ --release-channel=rapid
GKE は、デプロイされたワークロードからのリクエストに応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。
クラスタと通信を行うように
kubectl
を構成します。gcloud container clusters get-credentials l4-demo --region=${REGION}
Standard
Cloud Shell で次のコマンドを実行して、GKE 用 Workload Identity 連携を使用する Standard クラスタを作成します。
gcloud container clusters create l4-demo --location ${REGION} \ --workload-pool ${PROJECT_ID}.svc.id.goog \ --enable-image-streaming \ --node-locations=$REGION-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --machine-type n2d-standard-4 \ --num-nodes 1 --min-nodes 1 --max-nodes 5 \ --release-channel=rapid
クラスタの作成には数分かかることもあります。
次のコマンドを実行して、クラスタのノードプールを作成します。
gcloud container node-pools create g2-standard-24 --cluster l4-demo \ --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest \ --machine-type g2-standard-24 \ --enable-autoscaling --enable-image-streaming \ --num-nodes=0 --min-nodes=0 --max-nodes=3 \ --node-locations $REGION-a,$REGION-c --region $REGION --spot
GKE は、LLM 用に次のリソースを作成します。
- Google Kubernetes Engine(GKE)Standard エディションの一般公開クラスタ。
- 0 ノードにスケールダウンされた
g2-standard-24
マシンタイプのノードプール。GPU をリクエストする Pod を起動するまで、GPU の料金は発生しません。このノードプールは Spot VM をプロビジョニングします。Spot VM はデフォルトの標準の Compute Engine VM よりも低価格ですが、可用性は保証されません。オンデマンド VM を使用するには、このコマンドから--spot
フラグとtext-generation-inference.yaml
構成のcloud.google.com/gke-spot
ノードセレクタを削除します。
クラスタと通信を行うように
kubectl
を構成します。gcloud container clusters get-credentials l4-demo --region=${REGION}
ワークロードを準備する
次のセクションでは、使用するモデルに応じてワークロードを設定する方法について説明します。
Llama 3 70b
デフォルトの環境変数を設定します。
export HF_TOKEN=HUGGING_FACE_TOKEN
HUGGING_FACE_TOKEN
は、HuggingFace トークンに置き換えます。HuggingFace トークンの Kubernetes Secret を作成します。
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
次の
text-generation-inference.yaml
Deployment マニフェストを作成します。Deployment は、クラスタ内のノード間で Pod の複数のレプリカを実行できる Kubernetes API です。このマニフェストの内容:
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
NUM_SHARD
は2
にする必要があります。 QUANTIZE
がbitsandbytes-nf4
に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、モデルの精度は低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
次のようにマニフェストを適用します。
kubectl apply -f text-generation-inference.yaml
出力は次のようになります。
deployment.apps/llm created
モデルのステータスを確認します。
kubectl get deploy
出力は次のようになります。
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 20m
実行中のデプロイのログを表示します。
kubectl logs -l app=llm
出力は次のようになります。
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Mixtral 8x7b
デフォルトの環境変数を設定します。
export HF_TOKEN=HUGGING_FACE_TOKEN
HUGGING_FACE_TOKEN
は、HuggingFace トークンに置き換えます。HuggingFace トークンの Kubernetes Secret を作成します。
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
次の
text-generation-inference.yaml
Deployment マニフェストを作成します。Deployment は、クラスタ内のノード間で Pod の複数のレプリカを実行できる Kubernetes API です。このマニフェストの内容:
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
NUM_SHARD
は2
にする必要があります。 QUANTIZE
がbitsandbytes-nf4
に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、これによりモデルの精度が低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
次のようにマニフェストを適用します。
kubectl apply -f text-generation-inference.yaml
出力は次のようになります。
deployment.apps/llm created
モデルのステータスを確認します。
watch kubectl get deploy
デプロイの準備が整うと、出力は次のようになります。監視を終了するには、「
CTRL + C
」と入力します。NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
実行中のデプロイのログを表示します。
kubectl logs -l app=llm
出力は次のようになります。
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Falcon 40b
次の
text-generation-inference.yaml
Deployment マニフェストを作成します。Deployment は、クラスタ内のノード間で Pod の複数のレプリカを実行できる Kubernetes API です。このマニフェストの内容:
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
NUM_SHARD
は2
にする必要があります。 QUANTIZE
がbitsandbytes-nf4
に設定されているため、モデルは 32 ビットではなく 4 ビットで読み込まれます。これにより、GKE は必要な GPU メモリの量を減らし、推論速度を向上させることができます。ただし、モデルの精度は低下する可能性があります。リクエストする GPU を計算する方法については、GPU の量の計算をご覧ください。
- このモデルには 2 つの NVIDIA L4 GPU が必要なため、
次のようにマニフェストを適用します。
kubectl apply -f text-generation-inference.yaml
出力は次のようになります。
deployment.apps/llm created
モデルのステータスを確認します。
watch kubectl get deploy
デプロイの準備が整うと、出力は次のようになります。監視を終了するには、「
CTRL + C
」と入力します。NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
実行中のデプロイのログを表示します。
kubectl logs -l app=llm
出力は次のようになります。
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
ClusterIP タイプの Service を作成する
次の
llm-service.yaml
マニフェストを作成します。apiVersion: v1 kind: Service metadata: name: llm-service spec: selector: app: llm type: ClusterIP ports: - protocol: TCP port: 80 targetPort: 8080
次のようにマニフェストを適用します。
kubectl apply -f llm-service.yaml
チャット インターフェースをデプロイする
Gradio を使用して、モデルを操作できるウェブ アプリケーションを作成します。Gradio は、chatbot のユーザー インターフェースを作成する ChatInterface ラッパーを含む Python ライブラリです。
Llama 3 70b
gradio.yaml
という名前のファイルを作成します。次のようにマニフェストを適用します。
kubectl apply -f gradio.yaml
Service の外部 IP アドレスを探します。
kubectl get svc
出力は次のようになります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
EXTERNAL-IP
列の外部 IP アドレスをコピーします。外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。
http://EXTERNAL_IP
Mixtral 8x7b
gradio.yaml
という名前のファイルを作成します。次のようにマニフェストを適用します。
kubectl apply -f gradio.yaml
Service の外部 IP アドレスを探します。
kubectl get svc
出力は次のようになります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
EXTERNAL-IP
列の外部 IP アドレスをコピーします。外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。
http://EXTERNAL_IP
Falcon 40b
gradio.yaml
という名前のファイルを作成します。次のようにマニフェストを適用します。
kubectl apply -f gradio.yaml
Service の外部 IP アドレスを探します。
kubectl get svc
出力は次のようになります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
EXTERNAL-IP
列の外部 IP アドレスをコピーします。外部 IP アドレスと公開ポートを指定して、ウェブブラウザでモデル インターフェースを表示します。
http://EXTERNAL_IP
GPU 数の計算
GPU の数は、QUANTIZE
フラグの値によって異なります。このチュートリアルでは、QUANTIZE
は bitsandbytes-nf4
に設定されています。これは、モデルが 4 ビットで読み込まれることを意味します。
700 億のパラメータ モデルでは、最低 40 GB の GPU メモリが必要です。これは 700 億 × 4 ビット(700 億 x 4 ビット = 35 GB)に相当し、5 GB のオーバーヘッドを考慮します。この場合、1 つの L4 GPU ではメモリが不足します。したがって、このチュートリアルの例では、2 つの L4 GPU メモリ(2 × 24 = 48 GB)を使用します。この構成は、L4 GPU で Falcon 40b または Llama 3 70b を実行するのに十分です。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
クラスタを削除する
このガイドで作成したリソースについて、Google Cloud アカウントに課金されないようにするには、GKE クラスタを削除します。
gcloud container clusters delete l4-demo --region ${REGION}