1. vLLM与K8s初识:vLLM是什么、为什么需要K8s、vLLM+K8s的典型架构

大家好,我是你们的老朋友,一个在AI运维和K8s圈子里摸爬滚打了好几年的工程师。今天咱们开始聊一个很有意思的话题——vLLM和K8s的结合。

说实话,我第一次接触vLLM的时候,心里想的是:“又一个推理框架?”但用了一段时间后,我发现这东西确实有两把刷子。咱们今天就从最基础的东西开始,把vLLM是什么、为什么需要K8s、以及它们俩怎么搭伙过日子,掰扯清楚。

1.1 vLLM是什么?

vLLM,全称是Virtual Large Language Model,说白了就是一个专门为LLM推理加速而生的框架。它的核心目标就一个:让你用更少的GPU,跑更多的请求。

我个人的理解是,vLLM就像是一个聪明的调度员。它不会傻傻地等一个请求处理完再处理下一个,而是把请求拆成小块,穿插着处理。这个技术叫PagedAttention,是vLLM的杀手锏。

核心要点:vLLM通过PagedAttention技术,实现了高效的KV Cache管理,显存利用率能提升2-4倍。我在项目中遇到过,同样的模型,用vLLM部署后,QPS直接翻了一倍多。

vLLM的几个关键特性,我列一下:

  • PagedAttention:把KV Cache分页管理,像操作系统的虚拟内存一样,按需分配
  • 连续批处理:请求不用排队等,可以动态插入和退出
  • 高性能推理:支持多种量化方式,比如FP16、INT8、INT4
  • 兼容OpenAI API:接口和OpenAI一致,迁移成本极低

嗯,这里要注意一点。vLLM虽然快,但它不是万能的。它主要针对的是在线推理场景,也就是那种需要低延迟、高吞吐的服务。如果你做的是离线批量处理,那可能用别的工具更合适。

1.2 为什么需要K8s?

好,vLLM咱们大概了解了。那问题来了:我本地跑得好好的,为啥非要上K8s?

你想想看,一个LLM服务上线后,会遇到什么情况?

  • 流量忽高忽低,白天人多,晚上人少
  • GPU节点偶尔会挂,需要自动恢复
  • 模型版本要更新,不能停服
  • 多个模型要共享GPU资源

这些场景,单机部署根本搞不定。K8s就是来解决这些问题的。

我曾经在一个项目里,用裸机部署了三个vLLM服务。结果半夜一台机器宕机了,第二天早上才发现,用户投诉了一堆。后来上了K8s,Pod挂了自动重启,节点挂了自动调度到其他机器上,省心多了。

K8s给vLLM带来的核心价值,我总结为三点:

能力 说明 我的经验
弹性伸缩 根据CPU/GPU利用率或请求数,自动扩缩Pod 我习惯用HPA配合自定义指标,效果比默认的好
自愈能力 Pod挂了自动重启,节点挂了自动迁移 记得配置好readiness probe,不然流量会打到未就绪的Pod
资源管理 精细控制GPU、内存、CPU的分配 GPU一定要设置requests和limits一致,避免资源争抢

避坑指南:我曾经犯过一个错误,没给vLLM的Pod设置GPU的limits,结果两个Pod抢同一块GPU,推理速度直接掉到原来的三分之一。记住,GPU资源一定要显式声明。

1.3 vLLM+K8s的典型架构

好了,两个主角都介绍完了。咱们来看看它们怎么配合。我画了一张架构图,帮你理解整个流程。

vLLM + K8s 典型架构图 用户/客户端 Ingress / 负载均衡 K8s Service Pod 1 vLLM 容器 (GPU) 模型: llama-7b Pod 2 vLLM 容器 (GPU) 模型: llama-13b Pod 3 vLLM 容器 (GPU) 模型: chatglm-6b K8s 节点池 (GPU节点: A100 / V100) HPA 根据 GPU 利用率自动扩缩 Pod 数量

这个架构图,说白了就是三层结构:

  1. 入口层:用户请求先打到Ingress,做负载均衡和域名路由
  2. 服务层:K8s Service负责把请求分发到后端的vLLM Pod
  3. 计算层:每个Pod里跑一个vLLM实例,挂载不同的模型

我个人的习惯是,每个Pod只部署一个模型。这样方便做独立的扩缩容和版本管理。比如llama-7b流量大了,我只扩这个Pod,不影响其他模型。

小技巧:如果你有多个模型,建议用不同的Deployment来管理。每个Deployment对应一个模型,配上独立的HPA策略。这样运维起来清晰很多。

1.4 一个简单的部署示例

光说不练假把式。我给大家看一个最基础的vLLM部署YAML,咱们感受一下。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-llama7b
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vllm
      model: llama7b
  template:
    metadata:
      labels:
        app: vllm
        model: llama7b
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        args: ["--model", "meta-llama/Llama-2-7b-chat-hf"]
        ports:
        - containerPort: 8000
        resources:
          requests:
            nvidia.com/gpu: 1
            memory: "16Gi"
            cpu: "4"
          limits:
            nvidia.com/gpu: 1
            memory: "16Gi"
            cpu: "4"
        env:
        - name: CUDA_VISIBLE_DEVICES
          value: "0"

这个YAML里,我特别强调两点:

  • GPU资源:requests和limits必须一致,避免多个Pod抢GPU
  • 模型路径:可以用HuggingFace的模型名,也可以挂载本地路径

嗯,这里要注意。如果你用的是本地模型,记得用PVC或者hostPath把模型文件挂载进去。不然每次Pod重启都要重新下载,那可就慢了。

1.5 本章小结

咱们今天聊了vLLM和K8s的初识。vLLM是个高效的推理框架,K8s是个强大的编排平台。它们俩结合,能解决LLM服务部署中的很多实际问题。

我个人觉得,vLLM+K8s这套组合,是目前LLM在线推理的最佳实践之一。当然,它也有自己的坑,比如GPU调度、显存管理这些,咱们后面会慢慢聊。

好,今天就到这里。记住一句话:vLLM负责快,K8s负责稳。两者结合,才能让LLM服务真正跑起来。


专注资料整理