GPU 共有スケジューリングを使用して GPU メモリをスライスし、単一の GPU 上で複数の推論サービスを実行します。
仕組み
GPU 共有スケジューリングアドオンは、Pod 間で GPU メモリをスライスします。各サービスは --gpumemory フラグで必要なメモリを指定します。スケジューラーは、要求された合計メモリがノードの物理容量に達するまで、同じ GPU ノード上に Pod を併置します。
障害分離よりも GPU 使用率の最大化が重要な場合は、GPU 共有スケジューリングを使用します。厳密な分離が必要な場合は、専用 GPU ノードを使用してください。
制限事項
-
ノード上のすべての Pod が要求する合計 GPU メモリは、ノードの物理 GPU メモリを超えてはなりません。
-
GPU アクセラレーションノードは、デフォルトで CUDA 11 を使用します。このガイドでは、CUDA 12.0 以降が必要です。
-
ack-kserve は Raw Deployment モード である必要があります。
前提条件
次のことを確認してください。
-
GPU アクセラレーションノードを備え、Kubernetes 1.22 以降を実行する Container Service for Kubernetes (ACK) マネージドクラスターまたは ACK 専用クラスター。詳細については、「クラスターへの GPU アクセラレーションノードの追加」または「GPU アクセラレーションノードを備えた ACK 専用クラスターの作成」をご参照ください。
-
GPU ノードに CUDA 12.0 以降がインストールされていること。デフォルトは CUDA 11 です。CUDA 12 を使用するには、
ack.aliyun.com/nvidia-driver-version:525.105.17タグをノードプールに追加してください。詳細については、「ノード上の NVIDIA GPU ドライバーバージョンのカスタマイズ」をご参照ください。 -
GPU 共有スケジューリングコンポーネントがクラスターにインストールされていること
-
Arena クライアント 0.9.15 以降。詳細については、「Arena クライアントの設定」をご参照ください。
-
cert-manager と ack-kserve がインストールされており、ack-kserve が Raw Deployment モード であること
ステップ1:モデルデータの準備
モデルを Object Storage Service (OSS) バケットまたは Apsara File Storage NAS (NAS) ファイルシステムに保存します。このガイドでは OSS を使用します。詳細については、「ossfs 1.0 静的プロビジョニングボリュームの使用」または「静的にプロビジョニングされた NAS ボリュームのマウント」をご参照ください。
-
Qwen1.5-0.5B-Chat モデルをダウンロードします。
git lfs install GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen1.5-0.5B-Chat.git cd Qwen1.5-0.5B-Chat git lfs pull -
モデルファイルを OSS バケットにアップロードします。
詳細については、「ossutil のインストール」をご参照ください。
ossutil mkdir oss://<your-bucket-name>/models/Qwen1.5-0.5B-Chat ossutil cp -r ./Qwen1.5-0.5B-Chat oss://<your-bucket-name>/models/Qwen1.5-0.5B-Chat -
次の設定で永続ボリューム (PV) を作成します。
設定項目 値 [永続ボリュームタイプ] OSS [名前] llm-model [アクセス認証情報] OSS バケットの AccessKey ID と AccessKey シークレット [バケット] 前の手順で作成した OSS バケット [OSS パス] /Qwen1.5-0.5B-Chat -
PV にバインドする永続ボリューム要求 (PVC) を作成します。
設定項目 値 [永続ボリューム要求タイプ] OSS [名前] llm-model [割り当てモード] [既存の永続ボリューム] [既存の永続ボリューム] [既存の永続ボリュームを選択] をクリックし、前の手順で作成した PV を選択します
ステップ2:推論サービスのデプロイ
それぞれ 6 GiB の GPU メモリを要求する 2 つの Qwen 推論サービスをデプロイします。コマンド間の違いは --name のみです。
最初のサービスを開始します。
arena serve kserve \
--name=qwen1 \
--image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm:0.4.1 \
--gpumemory=6 \
--cpu=3 \
--memory=8Gi \
--data="llm-model:/mnt/models/Qwen1.5-0.5B-Chat" \
"python3 -m vllm.entrypoints.openai.api_server --port 8080 --trust-remote-code --served-model-name qwen --model /mnt/models/Qwen1.5-0.5B-Chat --dtype=half --max-model-len=4096"
--name=qwen2 で 2 番目のサービスを開始します。
主なパラメーター:
| パラメーター | タイプ | 必須 | 説明 |
|---|---|---|---|
--name |
String | はい | サービス名。グローバルに一意である必要があります。 |
--image |
String | はい | コンテナイメージ。 |
--gpumemory |
Integer (GiB) | いいえ | GiB 単位の GPU メモリ割り当て。たとえば、--gpumemory=6 となります。ノード上の全サービスの合計は、物理 GPU メモリを超えてはなりません。 |
--cpu |
Integer | いいえ | vCPU 数。 |
--memory |
String | いいえ | RAM の割り当て。たとえば、8Gi となります。 |
--data |
String | いいえ | <pvc-name>:<container-path> 形式で、PVC をコンテナにマウントします。この例では、PVC llm-model が /mnt/models/Qwen1.5-0.5B-Chat にマウントされます。 |
ステップ3:推論サービスの確認
-
両方の Pod が同じ GPU ノードで実行されていることを確認します。
kubectl get pod -owide | grep qwen期待される出力:
qwen1-predictor-856568bdcf-5pfdq 1/1 Running 0 7m10s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none> qwen2-predictor-6b477b587d-dpdnj 1/1 Running 0 4m3s 10.130.XX.XX cn-beijing.172.16.XX.XX <none> <none>両方の Pod が同じノード (
cn-beijing.172.16.XX.XX) で実行されていることから、GPU 共有がアクティブであることがわかります。 -
Pod ごとの GPU メモリを確認します (サービスごとに 1 つのコマンド)。
kubectl exec -it qwen1-predictor-856568bdcf-5pfdq -- nvidia-smi # 最初のサービス kubectl exec -it qwen2-predictor-6b477b587d-dpdnj -- nvidia-smi # 2 番目のサービス各 Pod の期待される出力: 最初の推論サービスの GPU メモリ
Fri Jun 28 06:20:43 2024 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.161.07 Driver Version: 535.161.07 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | 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 Tesla V100-SXM2-16GB On | 00000000:00:07.0 Off | 0 | | N/A 39C P0 53W / 300W | 5382MiB / 6144MiB | 0% Default | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| +---------------------------------------------------------------------------------------+2 番目の推論サービスの GPU メモリ
Fri Jun 28 06:40:17 2024 +---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.161.07 Driver Version: 535.161.07 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | 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 Tesla V100-SXM2-16GB On | 00000000:00:07.0 Off | 0 | | N/A 39C P0 53W / 300W | 5382MiB / 6144MiB | 0% Default | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| +---------------------------------------------------------------------------------------+各 Pod には 6 GiB (6,144 MiB) の制限があることから、GPU メモリ共有が設定どおりに機能していることがわかります。
-
NGINX Ingress ゲートウェイ経由でテストリクエストを送信します。
curl -H "Host: $(kubectl get inferenceservice qwen1 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \ -H "Content-Type: application/json" \ http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/chat/completions \ -d '{ "model": "qwen", "messages": [{"role": "user", "content": "This is a test."}], "max_tokens": 10, "temperature": 0.7, "top_p": 0.9, "seed": 10 }'期待される出力:
{"id":"cmpl-bbca59499ab244e1aabfe2c354bf6ad5","object":"chat.completion","created":1719303373,"model":"qwen","choices":[{"index":0,"message":{"role":"assistant","content":"OK. What do you want to test?"},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":21,"total_tokens":31,"completion_tokens":10}}このレスポンスにより、推論サービスが正しく機能していることが確認できます。
(オプション) ステップ4:クリーンアップ
不要になったリソースを削除します。
推論サービスを削除します。
arena serve delete qwen1
arena serve delete qwen2
PVC と PV を削除します。
kubectl delete pvc llm-model
kubectl delete pv llm-model