将 LLM 作为微服务部署:基于 vLLM 生产栈掌握 GPU 调度与 KEDA 弹性伸缩
2026/7/30 20:47:10 网站建设 项目流程

将 LLM 作为微服务部署:基于 vLLM 生产栈掌握 GPU 调度与 KEDA 弹性伸缩

大语言模型不再是实验室里的“巨兽”,而应成为架构图中一个普通的微服务。本文将带你用 vLLM 生产栈在 Kubernetes 上部署 OpenAI 兼容的推理 API,并深入讲解 GPU 调度、KEDA 弹性扩缩容等生产必备技能,让 LLM 像普通微服务一样稳定、高效、可伸缩。


目录

  1. 为什么要把 LLM 当成微服务?

  2. vLLM:高性能推理引擎的首选

  3. vLLM Production Stack 全景

  4. Kubernetes GPU 调度实战

    • 4.1 启用 GPU 支持

    • 4.2 节点选择与污点容忍

    • 4.3 多实例共享 GPU:时间切片与 MIG

    • 4.4 模型预热与持久化

  5. KEDA 自动伸缩:让推理服务随流量波动

    • 5.1 为什么不用 HPA?

    • 5.2 暴露 vLLM 指标

    • 5.3 配置 KEDA ScaledObject

  6. 完整部署示例

  7. 监控与成本优化

  8. 总结


1. 为什么要把 LLM 当成微服务?

2026 年,AI 不再是独立系统,而是微服务架构中的一个专用服务层。推理服务作为这一层的核心,必须满足:

  • 独立部署与扩容:不能因为一个模型更新就重起整个业务集群

  • 弹性伸缩:白天请求高峰自动扩容,深夜无人时缩容甚至降到零

  • 统一治理:遵循服务网格、GitOps、可观测性等微服务标准

将 LLM 作为一个普通的微服务部署在 Kubernetes 上,正是实现这些目标的最佳路径。


2. vLLM:高性能推理引擎的首选

在众多推理框架中,vLLM 凭借PagedAttention连续批处理高吞吐脱颖而出,已成为工业界的默认选择。

vLLM 的核心优势:

  • OpenAI 兼容 API:直接提供/v1/chat/completions等接口,客户端无需修改代码

  • 极致的吞吐量:连续批处理将同构请求动态合并,GPU 利用率高达 90%+

  • KV‑cache 内存管理:PagedAttention 避免碎片化,支持更大的并发量

  • 多模型支持:兼容 Llama、Qwen、Mistral 等主流模型,量化和 LoRA 适配器也可即插即用

用 vLLM 启动一个兼容 OpenAI 的推理服务非常简单:

bash

vllm serve meta-llama/Llama-3-8B-Instruct --port 8000

但想要真正在生产环境稳定运行,还需要一套完整的“生产栈”。


3. vLLM Production Stack 全景

所谓 Production Stack,并不单指 vLLM 本身,而是一整套让推理服务具备生产级能力的组合:

text

┌─────────────┐ │ API 网关 │ (可选,限流/认证) └──────┬──────┘ │ ┌──────▼──────┐ │ vLLM Pod │ (多副本) └──────┬──────┘ │ ┌────────────┼────────────┐ │ │ │ GPU 调度 KEDA 弹性 Prometheus (Device (根据队列 监控导出 Plugin) 长度伸缩) 指标)

本篇重点关注GPU 调度KEDA 弹性伸缩两大支柱,这也是面试和实际生产中最容易被问到的难点。


4. Kubernetes GPU 调度实战

4.1 启用 GPU 支持

Kubernetes 通过Device Plugin机制管理 GPU。首先确保节点已安装 NVIDIA 驱动,然后部署 NVIDIA 设备插件:

bash

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/main/nvidia-device-plugin.yml

验证节点是否上报 GPU 资源:

bash

kubectl describe node <gpu-node> | grep nvidia.com/gpu

4.2 节点选择与污点容忍

为了避免普通工作负载占用宝贵的 GPU 节点,需要配合nodeSelector/affinityTaint/Toleration

给 GPU 节点打上标签和污点:

bash

kubectl label node gpu-node-1 accelerator=nvidia-a100 kubectl taint node gpu-node-1 nvidia.com/gpu=true:NoSchedule

在 Pod 中声明使用 GPU 并容忍污点:

yaml

spec: nodeSelector: accelerator: nvidia-a100 tolerations: - key: "nvidia.com/gpu" operator: "Equal" value: "true" effect: "NoSchedule" containers: - name: vllm resources: limits: nvidia.com/gpu: 1

4.3 多实例共享 GPU:时间切片与 MIG

很多场景下(例如小模型、QPS 不饱和),一张 A100 可以同时服务多个推理实例。共享方式有两种:

  • 时间切片(Time‑slicing):GPU 在多个 Pod 间交替使用,配置简单,适合轻量级并发。

  • MIG(Multi‑Instance GPU):将 GPU 硬件切分为独立实例,每个实例拥有专属显存和计算单元,适合严格的资源隔离。

以时间切片为例,在nvidia-device-plugin的 ConfigMap 中配置:

yaml

apiVersion: v1 kind: ConfigMap metadata: name: time-slicing-config data: time-slicing: |- version: v1 sharing: timeSlicing: resources: - name: nvidia.com/gpu replicas: 4 # 每张物理 GPU 虚拟为 4 份

之后 Pod 可以请求nvidia.com/gpu: 1,但实际只占用 1/4 的 GPU 时间。通过这种方式,可以在单张 T4 上同时跑 4~8 个小模型推理实例。

4.4 模型预热与持久化

大模型文件动辄几十 GB,每次 Pod 重启都重新下载不可接受。解决方案是使用PersistentVolume存储模型,或借助Init Container在 Pod 启动前将模型预下载到 emptyDir(可配合节点 SSD)。

yaml

volumes: - name: model-storage persistentVolumeClaim: claimName: llama3-8b-pvc initContainers: - name: model-downloader image: busybox command: ['sh', '-c', 'if [ ! -f /models/config.json ]; then echo "waiting for model..."; fi'] volumeMounts: - name: model-storage mountPath: /models

vLLM 启动时指定模型路径为/models即可直接加载。


5. KEDA 自动伸缩:让推理服务随流量波动

5.1 为什么不用 HPA?

Kubernetes 原生的 HPA 仅支持 CPU 和内存指标。推理服务的资源瓶颈在于GPU 显存和并发请求数,而不是 CPU。当 GPU 接近打满时,CPU 可能还很空闲;反之请求队列堆积时,即使 CPU 不高也需要扩容。

KEDA(Kubernetes Event-driven Autoscaling)可以基于任意事件(Prometheus 指标、消息队列长度等)驱动伸缩,非常适合推理场景。

5.2 暴露 vLLM 指标

vLLM 启动时会自动暴露 Prometheus 指标(默认端口 8000,路径/metrics)。其中有两个关键指标:

  • vllm:num_requests_running:当前正在处理的请求数

  • vllm:num_requests_waiting:排队等待的请求数

我们可以利用Prometheus Adapter将这些指标注册为 Kubernetes 的自定义指标,或直接使用 KEDA 的prometheus触发器。

5.3 配置 KEDA ScaledObject

安装 KEDA:

bash

helm repo add kedacore https://kedacore.github.io/charts helm install keda kedacore/keda --namespace keda --create-namespace

创建一个ScaledObject,根据等待请求数自动伸缩:

yaml

apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: vllm-scaler spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-deployment minReplicaCount: 1 maxReplicaCount: 10 triggers: - type: prometheus metadata: serverAddress: http://prometheus-operated.monitoring.svc:9090 metricName: vllm_num_requests_waiting query: | sum(rate(vllm:num_requests_waiting{app="vllm"}[1m])) threshold: "2" # 等待请求超过 2 就开始扩容 activationThreshold: "1"

逻辑解释
当排队请求数连续一段时间超过 2 时,KEDA 会逐步增加 vLLM 的副本数,直到队列被消化或达到最大副本数。流量下降后,KEDA 会等待冷却期(默认 300 秒)再缩容,避免频繁抖动。

你也可以使用 GPU 利用率作为触发指标,但请求队列长度更贴近“服务质量”——宁可多扩几个 Pod,也不让用户排队。


6. 完整部署示例

下面给出一个最小可行的 vLLM 生产部署 YAML,包含 GPU 调度和 KEDA 缩容支持。

vllm-deployment.yaml

yaml

apiVersion: apps/v1 kind: Deployment metadata: name: vllm-deployment labels: app: vllm spec: replicas: 1 selector: matchLabels: app: vllm template: metadata: labels: app: vllm spec: nodeSelector: accelerator: nvidia-a100 tolerations: - key: "nvidia.com/gpu" operator: "Equal" value: "true" effect: "NoSchedule" containers: - name: vllm image: vllm/vllm-openai:latest command: ["python3", "-m", "vllm.entrypoints.openai.api_server"] args: - "--model" - "/models/Llama-3-8B-Instruct" - "--port" - "8000" - "--max-model-len" - "4096" ports: - containerPort: 8000 resources: limits: nvidia.com/gpu: 1 readinessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 60 periodSeconds: 10 volumeMounts: - name: model-storage mountPath: /models volumes: - name: model-storage persistentVolumeClaim: claimName: llama3-8b-pvc

vllm-service.yaml

yaml

apiVersion: v1 kind: Service metadata: name: vllm-service spec: selector: app: vllm ports: - port: 8000 targetPort: 8000

vllm-scaledobject.yaml:使用上面 5.3 节的配置。

部署后,你的推理服务就可以像普通微服务一样,通过http://vllm-service:8000/v1/chat/completions接收请求,并根据负载自动扩缩容。


7. 监控与成本优化

可观测性

  • Grafana 仪表板:从 Prometheus 拉取vllm:num_requests_runningvllm:request_latency_seconds、GPU 利用率等指标,实时观察。

  • 分布式追踪:在 vLLM 前面挂 Envoy 或使用 OpenTelemetry,关联请求与后端推理耗时。

  • 日志:使用 Loki 收集 vLLM 日志,发现如 OOM、模型加载失败等问题。

成本控制

  • 缩容至零:对于低频使用的内部工具,可将minReplicaCount设为 0,KEDA 在有请求时自动拉起,空闲时彻底关闭。

  • 混合实例:核心副本使用按需 GPU,弹性副本使用竞价实例,通过节点标签分离。

  • GPU 共享:如 4.3 节所述,用时间切片提升 GPU 利用率,减少硬件投入。


8. 总结

通过 vLLM + Kubernetes + KEDA 的组合,我们将 LLM 从“脆弱的怪兽”变成“健壮的微服务”。你学到了:

  • 如何在 K8s 上为推理服务配置GPU 调度(设备插件、亲和性、共享技术)

  • 如何用KEDA基于推理请求队列自动扩缩容

  • 一套可复制的 vLLM 生产部署方案

这套技术栈正是 2026 年 “AI-Integrated 微服务” 理念的实践:让 AI 能力像数据库一样,以服务的形式安静地支撑业务,而不是推翻一切重来。


如果你在部署过程中遇到问题,或者有其他更好的 GPU 共享、弹性策略,欢迎在评论区交流。觉得有用就点个赞吧!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询