将 LLM 作为微服务部署:基于 vLLM 生产栈掌握 GPU 调度与 KEDA 弹性伸缩
大语言模型不再是实验室里的“巨兽”,而应成为架构图中一个普通的微服务。本文将带你用 vLLM 生产栈在 Kubernetes 上部署 OpenAI 兼容的推理 API,并深入讲解 GPU 调度、KEDA 弹性扩缩容等生产必备技能,让 LLM 像普通微服务一样稳定、高效、可伸缩。
目录
为什么要把 LLM 当成微服务?
vLLM:高性能推理引擎的首选
vLLM Production Stack 全景
Kubernetes GPU 调度实战
4.1 启用 GPU 支持
4.2 节点选择与污点容忍
4.3 多实例共享 GPU:时间切片与 MIG
4.4 模型预热与持久化
KEDA 自动伸缩:让推理服务随流量波动
5.1 为什么不用 HPA?
5.2 暴露 vLLM 指标
5.3 配置 KEDA ScaledObject
完整部署示例
监控与成本优化
总结
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/affinity和Taint/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_running、vllm: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 共享、弹性策略,欢迎在评论区交流。觉得有用就点个赞吧!