このチュートリアルでは、効率的でスケーラブルな推論を行うために、GKE で複数の GPU を使用して大規模言語モデル(LLM)をデプロイしてサービングする方法について説明します。複数の L4 GPU を使用する GKE クラスタを作成し、次のいずれかのモデルを処理するインフラストラクチャを準備します。
必要な GPU の数はモデルのデータ形式によって異なります。このチュートリアルでは、各モデルで 2 つの L4 GPU を使用します。詳細については、GPU の量の計算をご覧ください。
このチュートリアルは、LLM の提供に Kubernetes コンテナ オーケストレーション機能を使用する ML エンジニア、プラットフォーム管理者、オペレーター、データおよび AI スペシャリストを対象としています。 Google Cloudのコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。
このページを読む前に、次のことをよく理解しておいてください。
環境を準備する
Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
Cloud Shell を開くデフォルトの環境変数を設定します。
gcloud config set project PROJECT_ID gcloud config set billing/quota_project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export CONTROL_PLANE_LOCATION=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} \ --location=${CONTROL_PLANE_LOCATION} \ --release-channel=rapid
GKE は、デプロイされたワークロードからのリクエストに応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。
クラスタと通信を行うように
kubectl
を構成します。gcloud container clusters get-credentials l4-demo --location=${CONTROL_PLANE_LOCATION}
Standard
Cloud Shell で次のコマンドを実行して、GKE 用 Workload Identity 連携を使用する Standard クラスタを作成します。
gcloud container clusters create l4-demo \ --location ${CONTROL_PLANE_LOCATION} \ --workload-pool ${PROJECT_ID}.svc.id.goog \ --enable-image-streaming \ --node-locations=${CONTROL_PLANE_LOCATION}-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 \ --location ${CONTROL_PLANE_LOCATION} \ --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 ${CONTROL_PLANE_LOCATION}-a,${CONTROL_PLANE_LOCATION}-c \ --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 --location=${CONTROL_PLANE_LOCATION}
ワークロードを準備する
このセクションでは、使用するモデルに応じてワークロードを設定する方法について説明します。このチュートリアルでは、Kubernetes Deployment を使用してモデルをデプロイします。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。
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 マニフェストを作成します。このマニフェストの内容:
- このモデルには 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 マニフェストを作成します。このマニフェストの内容:
- このモデルには 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
デプロイの準備ができている場合、出力は次のようになります。
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
監視を終了するには、「
CTRL + C
」と入力します。実行中のデプロイのログを表示します。
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 マニフェストを作成します。このマニフェストの内容:
- このモデルには 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
デプロイの準備ができている場合、出力は次のようになります。
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
監視を終了するには、「
CTRL + C
」と入力します。実行中のデプロイのログを表示します。
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 を作成する
Pod をクラスタ内で公開し、他のアプリケーションから検出およびアクセスできるようにします。
次の
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 を実行するのに十分です。