3. vLLM 服务部署:用 Deployment 把模型跑起来
好,到了真正动手的环节了。
前面我们聊了 Ingress 的基本概念,也讲了 vLLM 是什么。但光说不练假把式,得先把 vLLM 服务本身部署到 K8s 里,后面才能谈怎么暴露它。
这一章,我们就用 Deployment 来部署 vLLM。说白了,就是写一个 YAML 文件,告诉 K8s:「嘿,帮我跑一个 vLLM 的容器,资源给够,环境变量配好。」
3.1 为什么用 Deployment,而不是 Pod?
你可能会想,直接跑个 Pod 不就行了?嗯,理论上可以。但我个人习惯,生产环境从来不用裸 Pod。
为什么?因为 Pod 挂了就真的挂了,没人管它。Deployment 不一样,它自带「自愈」能力——Pod 挂了,ReplicaSet 会重新拉一个起来。我在项目中遇到过,有一次节点宕机,裸 Pod 直接消失,业务中断了半小时。换成 Deployment 后,同样的故障,十几秒就恢复了。
所以,记住一句话:用 Deployment,别用裸 Pod。
3.2 编写 vLLM 的 Deployment YAML
直接上代码。这是我常用的一个模板,你拿过去改改就能用。
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-server
namespace: default
labels:
app: vllm
spec:
replicas: 1
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
name: http
env:
- name: MODEL_NAME
value: "Qwen/Qwen2.5-7B-Instruct"
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-secret
key: token
- name: CUDA_VISIBLE_DEVICES
value: "0"
resources:
requests:
memory: "16Gi"
cpu: "4"
nvidia.com/gpu: 1
limits:
memory: "32Gi"
cpu: "8"
nvidia.com/gpu: 1
command:
- python3
- -m
- vllm.entrypoints.openai.api_server
args:
- --model
- $(MODEL_NAME)
- --port
- "8000"
- --max-model-len
- "8192"
- --gpu-memory-utilization
- "0.9"
- --trust-remote-code
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 5
核心要点:
- 镜像:我用的是
vllm/vllm-openai:latest,建议你固定版本号,比如v0.6.0,避免意外升级。 - 端口:vLLM 默认监听 8000 端口,对外提供 OpenAI 兼容的 API。
- 启动命令:直接调用了 vLLM 的入口模块,参数通过环境变量传入。
3.3 配置资源限制:别让模型把集群吃垮
大模型推理是出了名的「吃资源」。我曾经见过有人没配资源限制,一个 Pod 把整台机器的显存占满,导致其他服务全部 OOM。嗯,那场面,挺尴尬的。
资源限制怎么配?
- GPU:必须配。vLLM 依赖 GPU 做推理,不配的话调度器不会给你分配 GPU。
- 内存:7B 模型建议至少 16Gi,13B 模型建议 32Gi 起步。我一般把 requests 设低一点,limits 设高一点,给点缓冲。
- CPU:其实推理主要靠 GPU,CPU 用来做预处理和后处理。4 核起步,8 核比较稳。
⚠️ 注意:
如果你用的是 NVIDIA GPU,别忘了安装 nvidia-device-plugin。否则你配了 nvidia.com/gpu: 1 也没用,调度器根本不认。
3.4 配置环境变量:灵活一点,别写死
环境变量是 Deployment 的「灵魂」。我习惯把模型名称、Hugging Face Token 这些可变的东西都放到环境变量里,而不是硬编码在启动命令中。
| 环境变量 | 说明 | 示例值 |
|---|---|---|
MODEL_NAME |
模型名称,从 Hugging Face 拉取 | Qwen/Qwen2.5-7B-Instruct |
HF_TOKEN |
Hugging Face 的访问令牌,用于下载私有模型 | 从 Secret 中引用 |
CUDA_VISIBLE_DEVICES |
指定使用哪块 GPU | 0 或 0,1 |
MAX_MODEL_LEN |
最大输入长度,影响显存占用 | 8192 |
GPU_MEMORY_UTILIZATION |
GPU 显存利用率,0.9 表示用 90% | 0.9 |
💡 我的小技巧:
敏感信息(比如 HF_TOKEN)千万别直接写在 YAML 里。用 Secret 资源存起来,然后通过 valueFrom.secretKeyRef 引用。这样既安全,又方便换 Token。
3.5 健康检查:让 K8s 知道你的服务还活着
Deployment 配了健康检查,K8s 才能自动帮你处理故障。
- livenessProbe:探测 Pod 是否还活着。如果挂了,K8s 会重启它。
- readinessProbe:探测 Pod 是否准备好接收流量。如果没准备好,Service 不会把流量转发过来。
vLLM 自带了 /health 端点,直接拿来用就行。注意 initialDelaySeconds 要设大一点,因为模型加载需要时间。7B 模型大概 30-60 秒,13B 模型可能要 2-3 分钟。
3.6 本章核心逻辑图
下面这张图,帮你理清 Deployment 部署 vLLM 的整体流程:
流程很简单:你写好 YAML → 提交给 K8s → Scheduler 找个合适的节点 → 拉起 Pod,加载模型,开始提供服务。
3.7 部署验证
YAML 写好了,怎么验证它能不能跑?
- 检查 Pod 状态:
kubectl get pods -l app=vllm,看到Running就对了。 - 看日志:
kubectl logs -f <pod-name>,如果看到Uvicorn running on http://0.0.0.0:8000,说明模型加载成功。 - 测试 API:
kubectl port-forward pod/<pod-name> 8000:8000,然后本地 curl 一下/v1/models端点,看能不能返回模型列表。
常见坑:
- Pod 一直 Pending:大概率是 GPU 资源不够,或者没装 nvidia-device-plugin。
- Pod 反复 CrashLoopBackOff:可能是显存不够,模型加载到一半就 OOM 了。试试调小
--max-model-len或--gpu-memory-utilization。 - 健康检查失败:模型加载慢,
initialDelaySeconds设得太短。我一般设 120 秒起步。
好了,Deployment 部署 vLLM 就这些内容。说白了,就是配好镜像、资源、环境变量,再加个健康检查。你照着上面的 YAML 改一改,应该就能跑起来。
下一章,我们会给这个 Deployment 配上 Service,让集群内部能访问它。嗯,到时候再聊。
公众号:蓝海资料掘金营,微信 deep3321