2.13. 複数の GPU ノードを使用したモデルのデプロイ
大規模言語モデル (LLM) などの大規模モデルを処理するために、複数の GPU ノードにわたってモデルをデプロイします。
この手順では、vLLM サービングフレームワークを使用して、複数の GPU ノードにわたって Red Hat OpenShift AI 上でモデルを提供する方法を説明します。マルチノード推論では、vllm-multinode-runtime
カスタムランタイムを使用します。vllm-multinode-runtime
ランタイムは、VLLM ServingRuntime for KServe と同じイメージを使用し、マルチ GPU 推論に必要な情報を含んでいます。
複数の GPU ノードを使用したモデルのデプロイ は、現在、Red Hat OpenShift AI のテクノロジープレビュー機能として提供されています。テクノロジープレビュー機能は、Red Hat 製品のサービスレベルアグリーメント (SLA) の対象外であり、機能的に完全ではないことがあります。Red Hat では、実稼働環境での使用を推奨していません。テクノロジープレビュー機能は、最新の製品機能をいち早く提供して、開発段階で機能のテストを行い、フィードバックを提供していただくことを目的としています。
Red Hat のテクノロジープレビュー機能のサポート範囲に関する詳細は、テクノロジープレビュー機能のサポート範囲 を参照してください。
前提条件
- OpenShift クラスターのクラスター管理者権限を持っている。
- OpenShift コマンドラインインターフェイス (CLI) がダウンロードおよびインストールされている。詳細は、OpenShift CLI のインストール を参照してください。
Node Feature Discovery Operator、NVIDIA GPU Operator など、お使いの GPU タイプ用の Operator を有効にした。アクセラレーターの有効化の詳細は、アクセラレーターの有効化 を参照してください。
-
NVIDIA GPU (
nvidia.com/gpu
) を使用している。 -
ServingRuntime
またはInferenceService
のいずれかを使用して GPU タイプを指定した。ServingRuntime
で指定された GPU タイプがInferenceService
で設定されたものと異なる場合、両方の GPU タイプがリソースに割り当てられ、エラーが発生する可能性があります。
-
NVIDIA GPU (
- クラスターで KServe を有効にした。
-
環境にヘッド Pod が 1 つだけある。
InferenceService
のmin_replicas
またはmax_replicas
設定を使用してレプリカ数を調整しないでください。追加のヘッド Pod を作成すると、それらが Ray クラスターから除外される可能性があります。 - 永続ボリューム要求 (PVC) が設定済みで、ReadWriteMany (RWX) アクセスモード用に設定されている。
手順
ターミナルウィンドウで、クラスター管理者として OpenShift クラスターにまだログインしていない場合は、次の例に示すように OpenShift CLI にログインします。
$ oc login <openshift_cluster_url> -u <admin_username> -p <password>
モデルをデプロイするための namespace を選択または作成します。たとえば、次のコマンドを実行して、
kserve-demo
namespace を作成できます。oc new-project kserve-demo
モデルをデプロイする namespace から、モデルストレージ用の PVC を作成します。
Filesystem volumeMode
を使用してストレージクラスを作成します。PVC にこのストレージクラスを使用します。ストレージサイズは、ディスク上のモデルファイルのサイズよりも大きくする必要があります。以下に例を示します。注記PVC をすでに設定している場合は、このステップをスキップできます。
kubectl apply -f - apiVersion: v1 kind: PersistentVolumeClaim metadata: name: granite-8b-code-base-pvc spec: accessModes: - ReadWriteMany volumeMode: Filesystem resources: requests: storage: <model size> storageClassName: <storage class>
モデルを PVC にダウンロードするには、提供されているサンプル YAML を変更します。
apiVersion: v1 kind: Pod metadata: name: download-granite-8b-code labels: name: download-granite-8b-code spec: volumes: - name: model-volume persistentVolumeClaim: claimName: granite-8b-code-claim restartPolicy: Never initContainers: - name: fix-volume-permissions image: quay.io/quay/busybox@sha256:92f3298bf80a1ba949140d77987f5de081f010337880cd771f7e7fc928f8c74d command: ["sh"] args: ["-c", "mkdir -p /mnt/models/$(MODEL_PATH) && chmod -R 777 /mnt/models"] 1 volumeMounts: - mountPath: "/mnt/models/" name: model-volume env: - name: MODEL_PATH value: <model path> 2 containers: - resources: requests: memory: 40Gi name: download-model imagePullPolicy: IfNotPresent image: quay.io/opendatahub/kserve-storage-initializer:v0.14 3 args: - 's3://$(BUCKET_NAME)/$(MODEL_PATH)/' - /mnt/models/$(MODEL_PATH) env: - name: AWS_ACCESS_KEY_ID value: <id> 4 - name: AWS_SECRET_ACCESS_KEY value: <secret> 5 - name: BUCKET_NAME value: <bucket_name> 6 - name: MODEL_PATH value: <model path> 7 - name: S3_USE_HTTPS value: "1" - name: AWS_ENDPOINT_URL value: <AWS endpoint> 8 - name: awsAnonymousCredential value: 'false' - name: AWS_DEFAULT_REGION value: <region> 9 - name: S3_VERIFY_SSL value: 'true' 10 volumeMounts: - mountPath: "/mnt/models/" name: model-volume
- 1
chmod
操作は、Pod が root として実行されている場合にのみ使用できます。Pod を root として実行していない場合は、引数から `chmod -R 777` を削除します。- 2 7
- モデルへのパスを指定します。
- 3
InferenceService
にあるcontainers.image
の値。この値にアクセスするには、oc get configmap inferenceservice-config -n redhat-ods-operator -oyaml | grep kserve-storage-initializer:
のコマンドを実行します。- 4
- S3 バケットへのアクセスキー ID。
- 5
- S3 バケットへのシークレットアクセスキー。
- 6
- S3 バケットの名前。
- 8
- S3 バケットへのエンドポイント。
- 9
- AWS S3 バケットを使用する場合の S3 バケットのリージョン。ODF や Minio などの他の S3 互換ストレージを使用する場合は、
AWS_DEFAULT_REGION
環境変数を削除できます。 - 10
- SSL エラーが発生した場合は、
S3_VERIFY_SSL
をfalse
に変更します。
vllm-multinode-runtime
カスタムランタイムを作成します。oc process vllm-multinode-runtime-template -n redhat-ods-applications|oc apply -n kserve-demo -f -
次の
InferenceService
設定を使用してモデルをデプロイします。apiVersion: serving.kserve.io/v1beta1 kind: InferenceService metadata: annotations: serving.kserve.io/deploymentMode: RawDeployment serving.kserve.io/autoscalerClass: external name: <inference service name> spec: predictor: model: modelFormat: name: vLLM runtime: vllm-multinode-runtime storageUri: pvc://<pvc name>/<model path> workerSpec: {}
InferenceService
には次の設定を追加できます。-
workerSpec.tensorParallelSize
: ノードごとに使用される GPU の数を決定します。ヘッドノードとワーカーノードのデプロイメントリソースの GPU タイプ数は、どちらも自動的に更新されます。workerSpec.tensorParallelSize
の値は、必ず1
以上にしてください。 -
workerSpec.pipelineParallelSize
: デプロイメントでモデルのバランスをとるために使用されるノードの数を決定します。この変数は、ヘッドノードとワーカーノードの両方を含むノードの合計数を表します。workerSpec.pipelineParallelSize
の値は、必ず2
以上にしてください。実稼働環境では、この値は変更しないでください。
-
お使いの環境およびモデルサイズに応じて、追加の引数を指定する必要がある場合があります。
検証
複数の GPU ノードにモデルをデプロイするように環境を設定したことを確認するには、GPU リソースのステータス、InferenceService
のステータス、Ray クラスターのステータスを確認し、モデルにリクエストを送信します。
GPU リソースのステータスを確認します。
ヘッドノードとワーカーノードの Pod 名を取得します。
# Get pod name podName=$(oc get pod -l app=isvc.granite-8b-code-base-pvc-predictor --no-headers|cut -d' ' -f1) workerPodName=$(oc get pod -l app=isvc.granite-8b-code-base-pvc-predictor-worker --no-headers|cut -d' ' -f1) oc wait --for=condition=ready pod/${podName} --timeout=300s # Check the GPU memory size for both the head and worker pods: echo "### HEAD NODE GPU Memory Size" kubectl exec $podName -- nvidia-smi echo "### Worker NODE GPU Memory Size" kubectl exec $workerPodName -- nvidia-smi
応答の例
+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 550.90.07 Driver Version: 550.90.07 CUDA Version: 12.4 | |-----------------------------------------+------------------------+----------------------+ | 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 A10G On | 00000000:00:1E.0 Off | 0 | | 0% 33C P0 71W / 300W |19031MiB / 23028MiB <1>| 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ ... +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 550.90.07 Driver Version: 550.90.07 CUDA Version: 12.4 | |-----------------------------------------+------------------------+----------------------+ | 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 A10G On | 00000000:00:1E.0 Off | 0 | | 0% 30C P0 69W / 300W |18959MiB / 23028MiB <2>| 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+
<1> と <2> の値をチェックして、モデルが適切にロードされたことを確認します。モデルがロードされなかった場合、これらのフィールドの値は
0MiB
になります。
次のコマンドを使用して、
InferenceService
のステータスを確認します。注記: テクノロジープレビューでは、推論にポート転送のみを使用できます。oc wait --for=condition=ready pod/${podName} -n $DEMO_NAMESPACE --timeout=300s export MODEL_NAME=granite-8b-code-base-pvc
応答の例
NAME URL READY PREV LATEST PREVROLLEDOUTREVISION LATESTREADYREVISION AGE granite-8b-code-base-pvc http://granite-8b-code-base-pvc.default.example.com
モデルが推論に使用できることを確認するために、モデルにリクエストを送信します。
oc wait --for=condition=ready pod/${podName} -n vllm-multinode --timeout=300s oc port-forward $podName 8080:8080 & curl http://localhost:8080/v1/completions \ -H "Content-Type: application/json" \ -d "{ 'model': "$MODEL_NAME", 'prompt': 'At what temperature does Nitrogen boil?', 'max_tokens': 100, 'temperature': 0 }"