随着大语言模型(LLM)应用的日益普及,如何以较低的运营成本、更低的延迟,并有效分配 GPU 资源,成为了部署过程中的一大挑战。特别是对于 Qwen2.5-7B-Instruct 或 Mistral-Nemo-Instruct 这类相对较小的模型,在 NVIDIA H100、A200 等高性能 GPU 上部署时,往往会造成 GPU 资源的大量闲置。本文将深入探讨如何结合 Ray Serve 和 NVIDIA 的多实例 GPU(MIG)技术,优化 LLM 的部署,实现更高的 GPU 利用率,降低运营成本,并显著提升 LLM 应用的性能和响应速度。
NVIDIA MIG:GPU 资源精细划分的关键
在部署类似 Qwen2.5-7B-Instruct 或 LLaMA 8B 这样规模相对较小的 LLM 时,如果直接使用完整的 NVIDIA H100 GPU 进行推理,往往会造成严重的资源浪费。 NVIDIA MIG 技术应运而生,它允许将一块物理 GPU 划分为多个独立的 GPU 实例,每个实例都可以根据特定的工作负载需求进行量身定制。这使得我们可以将一块强大的 GPU 分配给多个较小的 LLM,避免资源浪费。
例如,一块 NVIDIA A100 GPU 可以通过 MIG 技术划分为多个较小的实例,每个实例可以分配不同的计算和内存资源。对于需要 40GB 显存的模型,可以划分一个 4g.40gb 的实例;而对于只需要 30GB 显存的模型,则可以划分一个 3g.40gb 的实例。这种精细的划分,能够最大程度地利用 GPU 资源,避免了资源浪费。
要配置 MIG,首先需要在支持 Ampere 或 Hopper 等架构的 NVIDIA GPU 的 Kubernetes 集群中安装 NVIDIA GPU Operator。然后,需要定义一个 ConfigMap,指定如何对 GPU 进行分区和配置。例如,可以禁用所有 GPU 的 MIG,或者仅在特定 GPU(例如 ID 为 0 和 1 的 GPU)上启用 MIG,并将它们划分为不同的实例。通过 kubectl 命令将 ConfigMap 应用到集群,并使用 kubectl patch 命令更新 Kubernetes 集群策略,使其使用混合策略,即为不同的 GPU 分配不同的 MIG 配置。最后,使用 kubectl label 命令标记 Kubernetes 节点,以激活 MIG 配置。
通过 nvidia-smi 命令可以验证 MIG 的配置是否生效。如果配置正确,可以看到 GPU 被划分为了多个 MIG 实例,并且每个实例都分配了相应的计算和内存资源。
Ray Serve:LLM 在生产环境中的高效部署框架
Ray Serve 是一个可扩展的模型服务库,用于构建在线推理 API。它能够将任何 Python 函数,甚至是整个机器学习管道,转化为高度可扩展、可用于生产环境的微服务,并且只需要最少的样板代码。在部署 LLM 时,Ray Serve 能够处理模型副本的启动、传入请求的路由、批处理以提高吞吐量以及基于实时负载的自动缩放等复杂任务。
Ray Serve 的强大之处在于其简洁的配置方式。只需要在 Kubernetes 友好的 RayService 清单(或者通过 Python API)中定义模型和扩展策略,Ray Serve 就可以处理资源分配,无论使用完整的 GPU、MIG 切片还是仅 CPU 节点,并确保低延迟、可靠的推理。
例如,可以使用 Ray Serve 部署多个不同的 LLM,并将它们暴露在同一个 API 端点下。Ray Serve 会根据请求的特征,自动将请求路由到相应的模型。此外,Ray Serve 还支持动态批处理,可以将多个请求合并成一个批次进行处理,从而提高吞吐量。
为了使用 Ray Serve,需要先安装 Kuberay Operator。然后,需要创建一个 Kubernetes Secret,其中包含 Hugging Face 访问令牌和 AWS 凭据,以便 Ray Serve 可以访问 Hugging Face 模型仓库和 AWS S3 存储桶。接下来,需要定义 RayService 自定义资源。RayService 允许在一个 YAML 清单中声明 Ray 集群和 Ray Serve 应用程序。通过 RayService,可以指定 head 和 worker pod 的设置(CPU、GPU、镜像、环境变量),以及 Serve 部署、路由和自动缩放策略。Ray Operator 会自动启动 Ray 控制平面、worker 池和模型服务端点,并处理扩展、容错和批处理。
RayService 配置详解:模型部署与集群管理
在 RayServe 的 ServeConfigV2 中,LLM 的 Serve 配置被组织成三个核心部分。model_loading_config
指定要加载的模型以及来自何处(例如,特定的 Hugging Face 仓库或云存储),确保下载正确的权重和 tokenizer。engine_kwargs
(目前仅 vLLM 是唯一支持的后端引擎)定义了推理引擎的运行时行为,包括精度设置、对 LoRA 微调适配器的支持以及其他功能。deployment_config
涵盖了 Ray Serve 自动缩放和部署参数,例如,它设置了最小和最大副本数以及并发目标(每个副本的正在进行的请求阈值,该阈值会触发缩放)。
Ray Cluster Config 用于在 Kubernetes 环境中基于 KubeRay 设置 Ray 集群。enableInTreeAutoscaling: true
设置 KubeRay 自动缩放,这会将一个自动缩放 sidecar 注入到 head pod 中,以基于实时需求自动调整 worker pod 计数在指定的 minReplicas
和 maxReplicas
之间。headGroupSpec
然后配置 Ray head 节点,设置启动参数(num-cpus: "0"
,以防止在 head pod 上安排应用程序,以及 dashboard-host: "0.0.0.0"
),分配 CPU 和内存资源(2 个 CPU,4 GiB)并设置其他环境变量。在 workerGroupSpecs
下,定义 LLM 推理 worker,分配资源,主要是 GPU(nvidia.com/mig-4g.40gb: "1"
和 nvidia.com/mig-3g.40gb: "1"
)。还需要使用环境变量和先前定义的 K8s Secret 注入 Hugging Face 和 AWS 凭据。
配置完成后,可以使用 kubectl apply -f ray-service.llm-serve.yaml
命令将配置应用到 Kubernetes 集群。可以使用 kubectl get rayservice ray-serve-llm -o yaml
命令检查 RayService 资源是否健康。还可以通过 exec 进入 head pod 运行 ray status -v
命令,确认控制平面和所有 worker 节点是否健康,并通过 exec 进入 worker pod 运行 nvidia-smi
命令,验证 GPU 资源的分配情况。
实战:Ray Serve 与 MIG 结合的 LLM 部署案例
假设我们需要部署两个 LLM:Qwen2.5-7b-instruct 和 Qwen3-8b。Qwen2.5-7b-instruct 需要 4GB 的 GPU 显存,而 Qwen3-8b 需要 3GB 的 GPU 显存。我们可以使用 MIG 技术将一块 NVIDIA A100 GPU 划分为一个 4g.40gb 的实例和一个 3g.40gb 的实例,并将这两个实例分配给两个 LLM。
接下来,可以使用 Ray Serve 部署这两个 LLM。在 RayService 的 workerGroupSpecs 中,需要指定每个 worker pod 需要的 GPU 资源。例如,可以指定一个 worker pod 需要一个 4g.40gb 的 GPU 实例和一个 3g.40gb 的 GPU 实例。Ray Serve 会自动将请求路由到相应的 worker pod,从而实现两个 LLM 的并行处理。
通过这种方式,我们可以在同一块 GPU 上同时运行多个 LLM,从而最大程度地利用 GPU 资源。此外,Ray Serve 的自动缩放功能可以根据负载情况动态调整 worker pod 的数量,从而保证 LLM 应用的性能和可用性。
请求发送与 Dashboard 设置:监控 LLM 应用
通过端口转发 Serve 应用程序 Service(例如,svc/ray-commotion-llm-serve-svc
)或 Head 应用程序 Service 到本地 8000 端口,可以访问 Ray Serve LLM 端点:
kubectl port-forward svc/ray-commotion-llm-serve-svc 8000
此外,还可以通过端口转发 8000 端口从 Head 应用程序 Service 向 serve 应用程序发送请求。请记住,此 Kubernetes Service 仅在 Ray Serve 应用程序运行并准备就绪后才会启动。在 Ray 集群中的所有 pod 都启动并运行后,此过程需要几分钟。
可以使用 curl 命令向 LLM 应用发送请求:
curl --location 'http://localhost:8000/v1/chat/completions' \
--header 'Content-Type: application/json' \
--data '{
"model": "qwen3-8b",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Provide steps to serve an LLM using Ray Serve."
}
]
}'
Ray Services 附带一个嵌入式 Ray Dashboard,这是一个基于 Web 的 UI,提供了关键指标、图表和调试工具,可帮助监控和排查 Ray 应用程序的故障。要访问 Ray Dashboard,请使用以下命令从 Head 应用程序 Service 端口转发 8625 端口:
kubectl port-forward svc/ray-commotion-llm-head-svc 8625
“Cluster”选项卡允许用户查看有关 Ray 集群组件(例如 head 和 worker pod)的详细信息。切换到 Dashboard 上的 “Serve” 选项卡可检查应用程序的状态、部署、路由器、日志和其他关键详细信息。
Ray 的生态系统还支持高级可观测性功能,可以通过集成 Prometheus 和 Grafana 来增强监控功能。此设置支持系统指标的实时可视化,从而更深入地了解 Ray 应用程序和基础设施,从而促进主动管理和优化。官方 Ray 文档提供了有关在 Kubernetes 环境中使用 KubeRay 配置这些工具的详细指南。
总结:Ray Serve + MIG 的优势与局限
优势:
- 最大化 GPU 利用率,降低成本: 通过高效地在每个 GPU 上运行多个隔离的 LLM 工作负载,显著降低了成本。
- 简化部署和管理: 简化了不同模型的部署和管理以及快速 LoRA 微调适配。
- 提供响应式、自动缩放: 通过 Ray Serve 提供推理容量的响应式、自动缩放,无缝适应不同的工作负载。
局限性:
- 可能增加延迟: MIG 切片可能会引入延迟开销,从而可能影响单个推理响应时间。
- 仅限于较新的 NVIDIA GPU: MIG 技术仅限于较新的 NVIDIA GPU 架构,例如 Ampere 和 Hopper。
- 资源分配不够灵活: MIG 中刚性的 GPU 分区限制了适应性,可能会导致资源分配或碎片化的效率低下。
总而言之, Ray Serve 和 NVIDIA MIG 技术的结合为 LLM 的高效部署提供了强大的解决方案。通过精细化的资源划分和灵活的部署框架,可以最大限度地提高 GPU 利用率,降低运营成本,并显著提升 LLM 应用的性能和响应速度。 尽管存在一些局限性,但随着技术的不断发展,这些问题将会得到进一步的解决。