2.12. 使用多个 GPU 节点部署模型
在多个 GPU 节点间部署模型以处理大型模型,如大型语言模型(LLM)。
您可以使用 vLLM 服务框架在多个 GPU 节点上提供 Red Hat OpenShift AI 的模型。多节点 inferencing 使用 vllm-multinode-runtime 自定义运行时,它使用与 vLLM NVIDIA GPU ServingRuntime for KServe 运行时相同的镜像,还包括多 GPU 推断所需的信息。
您可以从持久性卷声明(PVC)或开放容器项目(OCI)容器镜像部署模型。
目前,Red Hat OpenShift AI 作为技术预览功能通过多个 GPU 节点部署模型。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围
先决条件
- 具有集群管理员特权。
- 您已下载并安装 OpenShift 命令行界面 (CLI)。如需更多信息 ,请参阅安装 OpenShift CLI。
您已为 GPU 类型启用了 Operator,如 Node Feature Discovery Operator、Nvidia GPU Operator。有关启用加速器的更多信息,请参阅启用加速器。
-
您使用 NVIDIA GPU (
nvidia.com/gpu)。 -
您已通过
ServingRuntime或InferenceService指定 GPU 类型。如果ServingRuntime中指定的 GPU 类型与InferenceService中设置的不同,则两个 GPU 类型都会分配给资源,并可能导致错误。
-
您使用 NVIDIA GPU (
- 您已在集群中启用了 KServe。
-
您设置中只有一个 head pod。不要在
InferenceService中使用min_replicas或max_replicas设置来调整副本数。创建其他 head pod 可能会导致它们排除在 Ray 集群中。 - 要从 PVC 部署 :您为 ReadWriteMany (RWX)访问模式设置并配置了持久性卷声明(PVC)。
从 OCI 容器镜像部署 :
- 您已在 OCI 容器镜像中存储了一个模型。
- 如果模型存储在私有 OCI 存储库中,则代表您配置了镜像 pull secret。
流程
在一个终端窗口中,如果您还没有以集群管理员登录到 OpenShift 集群,请登录 OpenShift CLI,如下例所示:
$ oc login <openshift_cluster_url> -u <admin_username> -p <password>选择或创建用于部署模型的命名空间。例如,运行以下命令来创建
kserve-demo命名空间:oc new-project kserve-demo(仅从 PVC 部署模型) 在要部署模型的命名空间中为模型存储创建一个 PVC。使用
Filesystem volumeMode创建存储类,并将这个存储类用于 PVC。存储大小必须大于磁盘上模型文件的大小。例如:注意如果您已经配置了 PVC 或从 OCI 容器镜像部署模型,您可以跳过此步骤。
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>创建 pod,将模型下载到您创建的 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-base-pvc 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.143 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
- 只有在 pod 以 root 用户身份运行时,才允许
chmod操作。如果您没有以 root 身份运行 pod,请从参数中删除'chmod -R 777'。 - 2 7
- 指定到模型的路径。
- 3
containers.image的值,位于您的InferenceService中。要访问这个值,请运行以下命令:oc get configmap inferenceservice-config -n redhat-ods-operator -oyaml | grep kserve-storage-initializer:- 4
- S3 存储桶的访问密钥 ID。
- 5
- S3 存储桶的 secret 访问密钥。
- 6
- S3 存储桶的名称。
- 8
- S3 存储桶的端点。
- 9
- 如果使用 AWS S3 存储桶,则 S3 存储桶的区域。如果使用其他 S3 兼容存储,如 ODF 或 Minio,您可以删除
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: <storage_uri_path>1 workerSpec: {}2 - 1
- 根据您的部署方法指定模型的路径:
-
对于 PVC:
pvc://<pvc_name>/<model_path> -
对于 OCI 容器镜像 :
oci://<registry_host>/<org_or_username>/<repository_name><tag_or_digest>
-
对于 PVC:
- 2
- 以下配置可以添加到
InferenceService中:-
workerSpec.tensorParallelSize:确定每个节点使用多少个 GPU。head 和 worker 节点部署资源中的 GPU 类型计数会自动更新。确保workerSpec.tensorParallelSize的值至少为1。 workerSpec.pipelineParallelSize: 确定使用多少个节点来平衡部署中的模型。此变量代表节点总数,包括头和 worker 节点。确保workerSpec.pipelineParallelSize的值至少为2。不要在生产环境中修改这个值。注意根据环境和模型大小,您可能需要指定其他参数。
-
通过应用
InferenceService配置来部署模型:oc apply -f <inference-service-file.yaml>
验证
要确认您已将环境设置为在多个 GPU 节点上部署模型,请检查 GPU 资源状态、InferenceService 状态、Ray 集群状态,并将请求发送到模型。
检查 GPU 资源状态:
检索 head 和 worker 节点的 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 }"