news 2026/9/11 7:36:44

大模型推理上云实战:VKE容器服务+vLLM部署全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型推理上云实战:VKE容器服务+vLLM部署全攻略

大模型推理的热度,这两年几乎全被模型参数和刷分霸屏。可真到了业务落地的阶段,大家才会在同一个地方停下来挠头:模型拿回来了,怎么稳定、弹性、安全地跑成一个线上服务?我前阵子把一套7B对话模型完整部署到容器服务VKE上,再配合vLLM做推理加速,整整跑了两周生产流量,今天就把这次踩出来的经验原原本本写下来。这是一篇偏实战的内容,也会把VKE与大模型推理相关的六大能力模块完整拆一遍。

我建议你按自己的角色挑着看:如果你偏平台或SRE,重点看能力模块和调度细节;如果你偏算法工程,重点看部署流程和问题排查。但不管你属于哪类,只要你的服务准备上容器、要用GPU、要对外提供大模型推理API,这篇文章都会比官方文档多给一层“现场感”。

1. 为什么大模型推理偏偏需要容器服务VKE

1.1 大模型推理部署的三个典型痛感

没亲手从零部署过大模型推理服务的人,很难理解为什么一个“模型加载然后调用”的过程会搞出那么多幺蛾子。首先,环境依赖极其脆弱。PyTorch版本、CUDA驱动、Python包、推理框架,任何一个版本对不上,服务要么直接起不来,要么跑几步就崩。同一个团队里,A用1.x版本的transformers,B用2.x,最后合并代码的时候光修依赖就够喝一壶。

其次,GPU资源不好管。一张A100上到底能塞几个模型,显存够不够,并发上来之后会不会OOM,这些不是靠肉眼看docker ps能解决的。更麻烦的是,不同模型对显存和算力的要求差异很大,直接把一整张卡独占给一个小模型,成本高到离谱,但如果把多个模型塞进一张卡,又得操心隔离和互相干扰。

第三,上线链路太长。以前部署一个模型服务,得单独写部署脚本、配服务发现、挂监控、设告警、打通网络策略,零零散散搞一两天都很正常。而且这些配置千奇百怪,换一个人就很难维护。我跟不少做AI平台的朋友聊过,大家的感觉出奇一致:模型的训练和微调倒是推进得挺快,反而是在“把模型变成服务”这一段,被各种工程问题拖慢了速度。

1.2 VKE这类托管容器服务的底层逻辑

容器服务VKE本质上就是一个托管的Kubernetes集群,但它不是简单帮你装好K8s就完事。它把Kubernetes的声明式API能力做成了云上的一等公民——节点不用你自己买自己装,弹性伸缩可以按配置自动扩缩,LB、存储、监控这些周边依赖都能用云产品原生对接。

这样带来的最大好处是,你不需要关心集群控制面怎么维护、etcd怎么备份、Node怎么驱逐重建。算法同学只要把一个推理镜像推上去,在VKE里写一份Deployment + Service的YAML,一个可对外提供服务的推理应用就上线了。从“我有一堆模型权重”到“模型在跑且能扛流量”,中间的距离被压缩到几十分钟。对大模型推理这种形态来说,这个压缩特别关键,因为在生产环境里你还需要面对显存争抢、冷启动、峰值流量、节点故障这些问题,不是一个模型文件就能解决的。

2. 六大能力模块拆解:VKE体系的骨架

2.1 弹性伸缩:把GPU节点按流量“吹大”和“捏小”

大模型推理服务的流量曲线通常不是平的,早晚高峰、运营活动、临时任务都可能带来突发流量。弹性伸缩这个模块,管的就是当流量变大时副本数能不能自动加上去,流量降下来时资源能不能收回来。

VKE的弹性伸缩我实际用下来,主要是两层结构:一层是Pod层面的HPA,根据CPU、内存或者自定义指标调整Deployment副本数;另一层是节点池层面的Cluster Autoscaler,当Pod调度不上时,自动在新节点池里拉起一批GPU节点,Pod跑完后没活干了再缩掉。

这里的重点在于“拿什么指标做伸缩”。纯CPU水位对大模型推理基本不适用,因为请求计算主要发生在GPU上,CPU利用率往往不高。我实际用的是vLLM暴露出来的自定义指标,比如vllm:num_requests_waiting(排队请求数)和vllm:num_generating(正在生成的请求数),结合Prometheus Adapter把指标喂给HPA。下面这个配置就是基于排队请求数做扩缩容的:

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: vllm-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: llama2-7b-inference minReplicas: 2 maxReplicas: 8 metrics: - type: Pods pods: metric: name: vllm_num_requests_waiting target: type: AverageValue averageValue: "8" behavior: scaleDown: stabilizationWindowSeconds: 600

stabilizationWindowSeconds设成600秒,是为了防止流量抖动导致副本频繁缩下去又扩上来。推理服务跟普通Web服务不太一样,Pod起来以后加载模型到显存需要一两分钟甚至更久,缩容太激进,模型的热数据刚准备好就被干掉了,相当浪费。宁可多留几个副本兜底,也别卡在扩容的等待时间上。

2.2 异构算力:一张卡跑多个模型的调度艺术

VKE底层接的是Kubernetes的Device Plugin机制,节点上有GPU的时候,它会向上报一个nvidia.com/gpu资源,Pod里声明limits: nvidia.com/gpu: "1",调度器就会把Pod调度到有GPU的节点上。

但真正让推理成本降下来的,是GPU共享与切分能力。一个7B模型在FP16下权重大概14GB,如果用一张80GB的A100独占,显存利用率只有20%不到,算力更是浪费不少。我这边做过几轮优化后,一般让两个到三个小型对话模型共享一张大卡,或者用NVIDIA MIG做硬隔离,效果比独占模式好得多。

调度策略上,有两个方向要提前想清楚。Kubernetes调度器默认会把Pod尽量打散到不同节点,这在普通服务里是高可用的好习惯,但在GPU推理里不一定合适。如果你的业务高峰明确、节点池要缩容,那就希望负载尽量集中到少数节点上,缩容时才能腾出空节点。VKE这类托管服务通常允许配置Binpack(集中)或Spread(打散)策略。

如果跑的是70B以上模型,单卡肯定放不下,需要做张量并行。这时调度要额外关注节点亲和性,两个Pod要落在同一台多卡机器上,而且要预留足够CPU内存。我见过因为调度策略没配好,两个并行分片被调度到不同机器,走网络做张量同步,推理时延直接翻了好几倍。所以部署前就要把nodeSelector、PodTopologySpread这些字段规划清楚,宁可多加两条约束,也别让调度器自由发挥。

2.3 存储与模型加速:几十GB权重文件怎么快速就位

部署大模型推理,千万别把模型权重打进容器镜像。7B模型权重十几GB,70B上百GB,镜像仓库会被压垮,节点拉镜像也会拉到怀疑人生。正确做法是:镜像里只放推理框架和依赖代码,权重文件放到外部存储,通过PV/PVC挂载进容器。

VKE支持的存储类型很丰富,按场景分大概这么几类:

  • 云盘(ESSD这类):单节点读写性能最好,适合模型固定挂载在一个Pod上的情况,但多副本之间没法共享。
  • 文件存储:多个副本可以同时挂载同一份模型文件,适合先共享读模型,每个Pod再写自己的本地缓存。
  • 对象存储:适合做模型文件的归档和分发,尤其模型版本多的时候,把历史版本放对象存储,需要时再拉到计算节点。

模型加载最怕冷启动。第一次启动时从远端拉十几GB文件,几十秒到几分钟就过去了。我在VKE里经常用的优化手段是:节点池制作自定义镜像时,提前把常用模型缓存到节点本地目录,Pod启动时直接从本地加载,而不是每次从对象存储拉。还有一个做法是给模型目录做一个简单的缓存层,同一节点上多个副本都是读同一份本地权重文件,热启动基本能控制在几秒内。

2.4 网络与流量接入:让请求低延迟抵达推理后端

推理服务对网络的要求比普通Web服务高,因为一次推理请求可能要持续几十秒甚至更久,且涉及到SSE流式输出。VKE的网络模式一般推荐VPC-CNI直通,Pod直接拿VPC地址,包转发路径短,性能优于传统的叠加网络。在压测里,这个差异在长连接高并发场景下会非常明显。

服务暴露方面,集群内部访问用ClusterIP,外部访问有四层LoadBalancer和七层Ingress两种选择。对推理API这类需要灵活的请求路由的业务,我一般会走Ingress。但注意,默认的Nginx Ingress配置对推理场景不太友好,响应体稍微大一点就会被缓冲,SSE流式输出会被卡住。需要在Ingress上追加类似这样的注解:

nginx.ingress.kubernetes.io/proxy-buffering: "off" nginx.ingress.kubernetes.io/proxy-read-timeout: "600" nginx.ingress.kubernetes.io/proxy-send-timeout: "600"

关闭缓冲后,模型生成一个token就能立即返回一个token,用户体验会好很多。同时把超时时间拉长,因为大模型生成几百个token确实可能需要一分钟量级,直接用默认的60秒超时,业务稍微长一点就会被网关掐断。

2.5 可观测性:从GPU温度到首token时延

部署完服务只是开始,真正考验人的是线上出问题的时候能不能快速定位。VKE配套的可观测体系里,我重点盯四类指标。

第一类是节点和Pod的常规指标,CPU、内存、磁盘。第二类是GPU指标,显存占用、GPU利用率、温度、功耗,这些在云监控里直接能看到。第三类是框架级指标,vLLM、TGI这类推理框架都会暴露自定义metrics,比如当前请求数、排队数、平均生成token数。第四类是业务指标,最重要的就是TTFT,首token时延,也就是用户发出请求到收到第一个token的时间。

我自己常用的告警阈值整理成了表格,方便直接抄:

指标项含义参考告警阈值
GPU 利用率计算单元占用比例持续超过90%且副本数已达上限
显存占用率显存水位超过85%持续5分钟
TTFT P99首token时延超过2秒
请求排队数等待中的请求数量平均值超过8

指标要联动起来看才有效。比如GPU利用率高但TTFT也高,说明算力饱和,应该扩容;GPU利用率低但TTFT高,那可能是网络或者并发调度出了问题,先把瓶颈找到再动资源。

2.6 安全与多租户隔离:非root跑服务才是基线

容器安全里有一条讲究:运行用户不要用root。大模型推理服务如果以root跑在容器里,一旦应用被攻破,攻击者拿到的就是容器内的最高权限,逃逸风险会显著升高。VKE底层的Kubernetes本身就有完整的安全原语,关键是你得愿意用起来。

在镜像里,我用Dockerfile显式创建一个普通用户,并把模型目录的属主交给他。直接在Dockerfile里固定用户和目录权限,比在运行参数里单独指定更不容易忘。

FROM vllm/vllm-openai:latest RUN useradd -m -u 1000 modeluser \ && mkdir -p /workspace /models \ && chown -R modeluser:modeluser /workspace /models USER modeluser

除了非root,还有几个安全项也值得检查:容器内开启runAsNonRoot: trueallowPrivilegeEscalation: false,避免提权;镜像推上去之前做一次漏洞扫描,别把带高危漏洞的基础镜像带到生产;团队共享集群时,用Namespace加上ResourceQuota限制每个团队的CPU、内存和GPU额度,防止某个团队把集群资源吃空。

3. 大模型推理的真实业务落地:vLLM部署全流程

3.1 前置准备与集群规划

我这次选的是7B规模对话模型,规格上单卡A10也就是24GB显存就能跑起来,但为了容错和并发,我最终用了A100 40G节点。选实例规格的时候要提前估算显存:FP16的7B权重约14GB,再加上KV Cache、激活值、CUDA上下文,留出40%甚至50%余量比较稳妥。下面这个表是我常用的规划参考:

模型规模约估显存占用建议实例
7B16GB~24GB单卡A10/A100 40G
13B28GB~40GB单卡A100 40G/80G
70B130GB~160GB2×A100 80G 或 4×A100 40G

创建VKE集群时,我开了两个节点池:CPU节点池用来跑业务网关和运维组件,GPU节点池专门跑推理服务。GPU节点池需要打开弹性伸缩,并且设置最小2台、最大6台,这样高峰期节点能自动扩出来,低谷期也能缩回去控制成本。网络选择VPC-CNI直通模式,方便后续挂负载均衡和腾讯云那类安全组策略。

3.2 镜像构建与推送

模型权重不进镜像,所以镜像本身不大。我用vLLM官方镜像作为基础层,把非root用户的配置写进去,然后构建并推送到镜像仓库。这里命令是通用的,无论你用的是VKE配套的镜像仓库,还是其他任意Registry,动作都是先tag再push:

docker build -t registry.example.com/llm/vllm_llama2_7b:1.0 . docker push registry.example.com/llm/vllm_llama2_7b:1.0

有一类镜像不要做进容器:体积巨大的模型权重、虚拟环境、临时缓存文件。镜像只保留Python代码、依赖和推理框架,这样拉起容器快、镜像仓库压力小、安全扫描也容易做。

3.3 在VKE上部署推理服务

部署推理服务我直接用一份Deployment YAML,把GPU资源、模型数据卷、安全配置一次性声明好:

apiVersion: apps/v1 kind: Deployment metadata: name: llama2-7b-inference namespace: llm spec: replicas: 2 selector: matchLabels: app: llama2-7b-inference template: metadata: labels: app: llama2-7b-inference spec: containers: - name: vllm image: registry.example.com/llm/vllm_llama2_7b:1.0 args: - "--model" - "/models/llama-2-7b-chat-hf" - "--served-model-name" - "llama2-7b" - "--tensor-parallel-size" - "1" - "--max-model-len" - "4096" ports: - containerPort: 8000 resources: limits: nvidia.com/gpu: "1" volumeMounts: - name: model-storage mountPath: /models securityContext: runAsNonRoot: true allowPrivilegeEscalation: false volumes: - name: model-storage persistentVolumeClaim: claimName: model-pvc

nvidia.com/gpu: "1"是让调度器从可用的GPU节点池找一台有卡的节点。max-model-len控制最大上下文长度,如果业务里长文本对话多,这个值要适当放大,但对应的KV Cache也会吃更多显存。我建议先用小并发验证一次,再逐步上调,别一上来就把显存打满。

3.4 让服务能被业务访问:Service与Ingress

Deployment跑起来之后,还需要一个Service把Pod的端口暴露出来。集群内部调用用ClusterIP就够,但要走外部API的话,我一般再挂Ingress做域名和路由管理。

apiVersion: v1 kind: Service metadata: name: llama2-7b-inference-svc namespace: llm spec: selector: app: llama2-7b-inference ports: - port: 8000 targetPort: 8000

Ingress部分除了前面提到的关闭缓冲、调大超时,还可以按路径把多个模型路由到不同的后端Service。比如/v1/llama2-7b指向7B模型,/v1/llama3-70b指向70B模型,对外看来就是一个API网关,实际上背后是多个推理服务在跑。这个路由方式对多模型平台非常实用。

3.5 弹性伸缩配置:按推理负载自适应扩展

Deployment部署完,我接着配置HPA和节点池弹性,让服务能在流量上来时自动扩容。HPA的配置在2.1里已经给了,这里再补一个关键点:GPU节点池的Cluster Autoscaler不要设置得太敏感,否则一次短时流量抖动就可能触发节点扩容,导致成本飙升。我一般把扩缩容的冷却时间拉到5分钟,节点空闲静默期也调长。

还有一个细节:HPA的minReplicas不要设置成1。大模型推理Pod缩到一个副本的时候,万一它挂了,新的Pod冷启动加载模型要好几分钟,服务直接断档。我习惯最低保底两个副本,既保证故障时还能有流量承接,也避免频繁扩容缩容。

3.6 轻量边缘推理可以作为页边补充:Jetson上跑llama.cpp

VKE承载的是云端集中式算力,但大模型推理不一定只在云上。像Jetson AGX Orin这类带GPU的边缘设备,配合llama.cpp这类针对CPU和轻量GPU优化的推理引擎,也能跑起来量化后的小模型。之前我把一个7B模型做4-bit量化后在Jetson上跑,推理速度虽然远不如A100,但对一些数据不出局的边缘场景已经够用。这类边缘设备的好处是部署在机房或现场,可以和云上VKE集群通过控制面打通,形成“云上做大模型、边缘做轻量推理”的混合架构。

4. 常见问题与排查技巧实录

4.1 GPU显存不足导致Pod一直Pending

这是新手上路最容易遇到的情况,现象是Pod一直处于Pending,登录VKE控制台看到事件里写着Insufficient nvidia.com/gpu。原因很简单:节点上的卡已经被其他Pod占满,或者剩余显存不够你声明的资源。排查时先看节点GPU分配情况,再看有没有其他模型把卡吃满了。有时候不是卡不够,而是只声明GPU数量、没声明显存,两个小模型同时被调度到同一张卡上,显存会爆。针对这种情况,我一般会约束同一张卡上的Pod数量,或者在业务低峰期手动缩到指定的副本数。

4.2 镜像拉取慢、容器启动慢

启动慢的原因分两种:镜像太大,或模型权重冷启动。镜像问题可以通过给推理镜像瘦身解决,把用不到的包全部清掉,基础镜像尽量选官方精简版。模型权重冷启动问题刚才也提到,最有效的办法是节点池预缓存。如果已经是预缓存了还是慢,检查一下文件存储或对象存储的带宽,带宽不够时大量并发读取会把存储打满,启动速度自然上不去。

4.3 非root用户没法写模型缓存目录

用非root用户跑容器之后,会遇到一个典型问题:模型缓存想写到某个目录,但权限不够,直接Permission denied。根源是Dockerfile里虽然创建了用户,但目录属主没切。解法就是在Dockerfile里把需要写入的目录chown给这个用户,或者用initContainer先改一遍数据卷的属主。千万不要因为懒得查权限就把用户改回root,安全底线会被突破。

4.4 扩容后冷启动时间太长

流量高峰时HPA触发扩容,新Pod拉起来后要加载十几GB的模型,前几分钟几乎无法应答请求。这会让扩容效果大打折扣。我的经验是双管齐下:一方面像前面说的,节点本地做模型缓存,甚至直接在节点池预加载;另一方面,给HPA设置更早的触发点,比如排队请求数超过4就扩容,趁流量还没完全打满,先把新副本预热起来。宁可多花一点GPU运行时间,也别让用户体验到“排队五分钟,超时一片”的情况。

4.5 推理时延抖动排查

时延抖动是线上最难缠的问题之一。有一次某模型P99时延突然从1秒飙到5秒,查了一圈发现是另一个团队的批量任务在同一时间挤到了同一张GPU卡上。因为GPU共享会引入算力争抢,推荐的做法是给不同模型或者不同团队打上不同的调度标签,让关键推理服务独占一部分算力节点,把批量任务和在线任务隔离开。还有一个隐蔽因素是CPU绑核,推理服务如果没绑定CPU,上下文切换也可能带来时延波动,在压测阶段就要留意。

4.6 常见问题速查表

问题现象可能原因优先排查命令/方法
Pod 一直 PendingGPU 资源不足kubectl describe pod <pod>看事件
显存 OOM并发过高或上下文过长降低 max-model-len,控制并发
镜像拉取很慢镜像过大把模型权重移出镜像
目录 Permission denied非root用户无权限检查Dockerfile USER与chown
扩容后仍超时模型冷启动节点预热 + HPA前移
响应被缓冲导致断流Ingress开启buffer关闭proxy-buffering
GPU利用率低但时延高算力争抢或网络瓶颈隔离节点,检查VPC-CNI模式

5. 写在最后:经验沉淀比功能堆叠更重要

从集群规划到vLLM跑通,再到现在稳定扛住线上流量,我最大的体会是:VKE这类容器服务确实把Kubernetes的复杂度做了很好的封装,但工具只是给了你一套框架,真正决定稳定性的还是使用姿势。弹性伸缩的指标选得对不对、GPU共享的隔离做得好不好、模型权重的分发链路通不通,这些才是大模型推理落地成败的关键。

如果让我给正准备做这件事的人一个建议,那就是先把“最小可用的推理链路”跑通,再逐步加弹性、加多模型、加GPU共享。一上来就追求复杂的调度和优化,反而容易在生产里埋坑。先把一个7B模型稳定地变成API,你就已经跑赢了大多数还在文档里打转的团队了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 7:36:34

Python自动化Excel操作实战:openpyxl高效数据处理

1. 为什么需要Python操作Excel&#xff1f;在数据处理领域&#xff0c;Excel长期占据着不可替代的地位。根据2023年最新的行业调研&#xff0c;超过78%的数据分析师日常工作中需要处理Excel文件。但手动操作不仅效率低下&#xff0c;还容易出错。这就是为什么我们需要用Python来…

作者头像 李华
网站建设 2026/9/11 7:33:27

OpenHarmony上基于Flutter的文本去重工具实战:从HashSet到Isolate优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 7:32:37

C++代码复杂度控制与优化实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 7:31:00

Java性能优化核心技能与实战经验分享

1. 互联网大厂Java程序员的真实能力画像 在技术社区里&#xff0c;我们经常能看到关于"大厂程序员是否都精通性能优化"的讨论。作为在多家头部互联网企业担任过技术面试官的从业者&#xff0c;我想通过实际案例和数据来还原这个问题的真相。 首先要明确的是&#xf…

作者头像 李华
网站建设 2026/9/11 7:26:39

GHelper:5分钟上手的华硕笔记本轻量控制工具

GHelper&#xff1a;5分钟上手的华硕笔记本轻量控制工具 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expertbook,…

作者头像 李华