1. vLLM与K8s基础:vLLM是什么、为什么选择K8s部署、vLLM在K8s中的典型架构

大家好,我是你们的老朋友。今天咱们正式开讲《vLLM显存溢出K8s报错解决实战》的第一章。说实话,这个系列我准备了很久,因为在实际项目中,vLLM和K8s的搭配确实坑不少。尤其是显存溢出(OOM)的问题,我当年第一次遇到时,差点把服务器重启了三遍才找到原因。

好,废话不多说。咱们先打好地基,搞清楚vLLM是什么,为什么非要用K8s来部署它,以及它们在K8s里到底长什么样。

1.1 vLLM是什么?

vLLM,全称是「Virtual Large Language Model」。说白了,它是一个专门为LLM推理加速而生的开源库。你想想看,大模型跑推理时,最头疼的是什么?显存!显存!还是显存!

vLLM的核心技术叫PagedAttention。嗯,这个名字你可能听过。它借鉴了操作系统的虚拟内存分页思想——把KV Cache切成小块,按需分配。这样一来,显存利用率能提升好几倍。

我在项目中遇到过这样一个场景:用HuggingFace的原生推理,一个13B模型要占40GB显存。换成vLLM后,同样的模型只用了18GB。你想想看,这差距有多大?

核心优势总结:

  • 高吞吐:连续批处理(Continuous Batching),请求来了不排队,直接塞进当前批次
  • 低显存:PagedAttention,KV Cache按需分配,不浪费一丁点
  • 易用性:兼容OpenAI API格式,一行代码就能切换

1.2 为什么选择K8s部署?

好,问题来了。vLLM这么好用,为什么非要上K8s?直接在单机上跑不行吗?

行,当然行。但你要考虑几个现实问题:

  • 资源弹性:大模型推理的负载波动很大。白天高峰期,可能同时有几百个请求;半夜低谷期,可能就几个人在用。K8s可以自动扩缩容,省成本。
  • 故障恢复:我遇到过GPU卡突然掉线的情况。单机部署的话,服务直接挂了。K8s有自愈能力,Pod挂了自动重启,或者调度到其他节点。
  • 多模型管理:你可能同时部署了7B、13B、70B好几个模型。K8s的命名空间和标签机制,能帮你把不同模型的服务隔离开。
  • GPU共享:K8s支持GPU的MPS(多进程服务)和MIG(多实例GPU),一块A100可以切成多个小GPU,跑多个小模型。

我的个人习惯: 只要模型推理服务需要对外提供API,我第一反应就是上K8s。单机部署只适合开发调试阶段。

1.3 vLLM在K8s中的典型架构

接下来,咱们看看vLLM在K8s里到底是怎么组织的。我画了一张架构图,你一看就明白。

vLLM在K8s中的典型架构 用户/客户端 Ingress / LoadBalancer Service (ClusterIP) Deployment (管理多个Pod副本) Pod 1 vLLM容器 GPU: 1x A100 Pod 2 vLLM容器 GPU: 1x A100 Pod 3 vLLM容器 GPU: 1x A100 用户请求 → Ingress → Service → Deployment → Pod (vLLM + GPU)

这张图展示了最标准的部署模式。我来拆解一下每一层的作用:

1.3.1 用户层

用户通过HTTP请求访问你的模型API。请求格式兼容OpenAI的Chat Completions接口。说白了,你原来怎么调GPT,现在就怎么调vLLM。

1.3.2 Ingress层

Ingress负责外部流量接入。我建议用Nginx Ingress Controller或者Traefik。它们可以帮你做SSL终止、限流、路径转发。我曾经踩过一个坑——没配Ingress的请求超时时间,结果长文本生成请求被截断了。嗯,后来加了nginx.ingress.kubernetes.io/proxy-read-timeout: "600"才解决。

1.3.3 Service层

Service是K8s内部的负载均衡器。vLLM的Pod可能会动态扩缩容,Service能自动发现新Pod,把请求分发过去。这里要注意,vLLM的API是长连接(SSE流式输出),所以Service的sessionAffinity最好设置为ClientIP,避免请求被转发到不同Pod导致流中断。

1.3.4 Deployment层

Deployment管理Pod的副本数。你可以设置replicas: 3,K8s会保证始终有3个vLLM实例在运行。如果某个Pod挂了,它会自动拉起一个新的。

避坑指南: 我曾经把replicas设得太大,结果集群GPU不够用,Pod一直处于Pending状态。后来我加了resources.limits.nvidia.com/gpu: 1,确保每个Pod只占1块GPU。

1.3.5 Pod内部

每个Pod里跑一个vLLM容器。容器启动命令大概是这样的:

python -m vllm.entrypoints.openai.api_server \
  --model /models/llama-13b \
  --tensor-parallel-size 1 \
  --gpu-memory-utilization 0.9 \
  --max-model-len 4096

这里有几个关键参数:

  • --tensor-parallel-size:如果你的Pod分配了多块GPU,可以设置这个参数做张量并行
  • --gpu-memory-utilization:控制显存利用率。我一般设0.9,留10%给系统和其他进程
  • --max-model-len:最大序列长度。设太大容易OOM,设太小又限制业务

1.4 典型部署场景对比

场景 推荐架构 说明
单模型单GPU Deployment + Service + Ingress 最简单,适合7B以下模型
单模型多GPU Deployment + StatefulSet + Headless Service 需要张量并行,Pod间通信用RDMA
多模型混合部署 多个Deployment + 统一Ingress + 路由规则 用Ingress的路径转发区分模型
高并发场景 HPA + Cluster Autoscaler 根据CPU/GPU利用率自动扩缩容

我的建议: 刚开始别搞太复杂。先跑一个Deployment + Service + Ingress的经典组合。等业务稳定了,再考虑HPA和Cluster Autoscaler。步子迈大了容易扯着蛋。

1.5 本章小结

好,咱们把第一章的内容捋一捋:

  • vLLM是一个高效的LLM推理引擎,核心是PagedAttention
  • K8s部署能解决资源弹性、故障恢复、多模型管理等问题
  • 典型架构是:用户 → Ingress → Service → Deployment → Pod (vLLM + GPU)
  • Pod启动时要注意显存利用率、模型长度等参数

下一章,咱们会深入分析vLLM在K8s中常见的显存溢出报错。说实话,那才是真正的硬仗。不过别担心,我会把每个坑的解法都掰开揉碎了讲给你听。


专注资料整理