主题
vLLM 推理服务部署指南
适用环境: K3s + HAMi vGPU 集群
vLLM 版本: v0.8.4
最后更新: 2026-08-22
目录
1. vLLM 简介
vLLM 是一个高性能大语言模型推理引擎,核心特性:
| 特性 | 说明 |
|---|---|
| PagedAttention | 将 KV Cache 按页管理,显存利用率提升 2-4x |
| Continuous Batching | 动态合并请求,吞吐量远超静态 batch |
| OpenAI 兼容 API | 原生支持 /v1/chat/completions、/v1/models 等接口 |
| 量化支持 | GPTQ、AWQ、FP8 等主流量化格式 |
| 多模态 | 支持 LLaVA、Qwen-VL 等视觉模型 |
架构示意
用户请求 → OpenAI API → vLLM Engine → Model (GPU)
↓ ↓
HTTP Server PagedAttention
(FastAPI) Continuous Batching
Token Scheduling版本选择建议
| 版本 | 适用场景 |
|---|---|
| v0.6.x | RTX 20 系列(compute 7.5),稳定性最佳 |
| v0.7.x | RTX 30/40 系列,支持 CUDA 12.4 |
| v0.8.x | 最新特性(chunked prefill、speculative decoding) |
2. 环境准备
2.1 前置条件
- Kubernetes 集群(K3s / K8s ≥ 1.19)
- HAMi vGPU 已安装(见
hami-vgpu-v100.md) - NFS 共享存储已挂载模型文件
- GPU 节点已标记
gpu=on
2.2 模型文件准备
将模型文件放置在 NFS 共享目录:
bash
# NFS 服务端(10.60.10.196)
sudo mkdir -p /model/ModelScope/Qwen
# 使用 ModelScope 下载(推荐国内)
pip install modelscope
python3 -c "
from modelscope import snapshot_download
snapshot_download('Qwen/Qwen2.5-0.5B-Instruct', cache_dir='/model/ModelScope/Qwen')
snapshot_download('Qwen/Qwen3-0.6B', cache_dir='/model/ModelScope/Qwen')
"
# 验证
ls -la /model/ModelScope/Qwen/Qwen2.5-0.5B-Instruct/
ls -la /model/ModelScope/Qwen/Qwen3-0.6B/2.3 创建 NFS PV/PVC
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-modelscope
spec:
capacity:
storage: 200Gi
accessModes:
- ReadWriteMany
storageClassName: nfs-modelscope
persistentVolumeReclaimPolicy: Retain
nfs:
path: /model/ModelScope
server: 10.60.10.196
readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-modelscope
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-modelscope
volumeName: nfs-modelscope
resources:
requests:
storage: 200Gibash
kubectl apply -f nfs-pv-pvc.yaml
kubectl get pv,pvc nfs-modelscope3. 国内镜像配置
3.1 vLLM 镜像拉取
bash
# 方案一:华为云镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai:v0.8.4
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai:v0.8.4 \
vllm/vllm-openai:v0.8.4
# 方案二:DaoCloud 加速
docker pull docker.m.daocloud.io/vllm/vllm-openai:v0.8.4
docker tag docker.m.daocloud.io/vllm/vllm-openai:v0.8.4 vllm/vllm-openai:v0.8.43.2 推送到本地 Registry
bash
REGISTRY="117.50.188.237:30000"
docker tag vllm/vllm-openai:v0.8.4 ${REGISTRY}/vllm/vllm-openai:v0.8.4
docker push ${REGISTRY}/vllm/vllm-openai:v0.8.4
curl -s http://${REGISTRY}/v2/vllm/vllm-openai/tags/list3.3 HuggingFace 镜像
yaml
env:
- name: HF_ENDPOINT
value: "https://hf-mirror.com"
---
## 4. 部署模板
### 4.1 通用 6GB vGPU 模板
适用于 RTX 3090 (24GB/4vGPU) 和 RTX 3080 Ti (12GB/2vGPU):
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-<model-name>
spec:
replicas: 1
selector:
matchLabels:
app: vllm-<model-name>
template:
metadata:
labels:
app: vllm-<model-name>
spec:
schedulerName: hami-scheduler
nodeSelector:
kubernetes.io/hostname: "<目标节点>"
containers:
- name: vllm
image: 117.50.188.237:30000/vllm/vllm-openai:v0.8.4
imagePullPolicy: IfNotPresent
args:
- --model
- /models/Qwen/<模型目录>
- --served-model-name
- <api-model-name>
- --port
- "8000"
- --device
- cuda
- --dtype
- float16
- --max-model-len
- "2048"
- --enforce-eager
- --max-num-seqs
- "4"
- --gpu-memory-utilization
- "0.95"
- --swap-space
- "0"
ports:
- containerPort: 8000
env:
- name: HF_ENDPOINT
value: "https://hf-mirror.com"
resources:
requests:
cpu: "500m"
memory: "2Gi"
nvidia.com/gpu: "1"
nvidia.com/gpumem: "6k"
limits:
memory: "6Gi"
nvidia.com/gpu: "1"
nvidia.com/gpumem: "6k"
volumeMounts:
- name: models
mountPath: /models
readOnly: true
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 3
volumes:
- name: models
persistentVolumeClaim:
claimName: nfs-modelscope
---
apiVersion: v1
kind: Service
metadata:
name: vllm-<model-name>
spec:
type: ClusterIP
selector:
app: vllm-<model-name>
ports:
- port: <service-port>
targetPort: 80004.2 小显存 4GB vGPU 模板
适用于 RTX 2080 (8GB/2vGPU):
yaml
# 与 6GB 模板差异:
# nvidia.com/gpumem: "4k"
# --max-model-len "1024"
# --max-num-seqs "2"
# 只能运行 ≤ 0.6B 参数模型4.3 部署步骤
bash
# 1. 复制模板并修改变量
cp vllm-6gb-template.yaml vllm-my-model.yaml
sed -i 's/<model-name>/my-model/g' vllm-my-model.yaml
sed -i 's/<目标节点>/10-60-205-41/g' vllm-my-model.yaml
sed -i 's|<模型目录>|Qwen/Qwen3-0.6B|g' vllm-my-model.yaml
sed -i 's/<api-model-name>/qwen3-0.6b/g' vllm-my-model.yaml
sed -i 's/<service-port>/8010/g' vllm-my-model.yaml
# 2. 部署
kubectl apply -f vllm-my-model.yaml
# 3. 验证
kubectl get pods -o wide | grep vllm5. 本集群完整部署清单
5.1 GPU 资源分配矩阵
| 节点 | GPU | 总显存 | vGPU 切分数 | 每 vGPU 显存 | 可运行模型 |
|---|---|---|---|---|---|
| 10-60-10-196 | RTX 2080 | 8GB | 2 | 4GB | Qwen3-0.6B only |
| 10-60-205-41 | RTX 3080 Ti | 12GB | 2 | 6GB | Qwen2.5-0.5B + Qwen3-0.6B |
| 10-60-18-8 | RTX 3090 | 24GB | 4 | 6GB | 最多 4 个模型实例 |
5.2 部署实例清单
| # | 部署名 | 模型 | 节点 | vGPU | 端口 |
|---|---|---|---|---|---|
| 1 | vllm-qwen25-05b | Qwen2.5-0.5B-Instruct | 10-60-18-8 (3090) | 6GB | 8001 |
| 2 | vllm-qwen3-06b | Qwen3-0.6B | 10-60-18-8 (3090) | 6GB | 8002 |
| 3 | vllm-qwen25-05b-3080ti | Qwen2.5-0.5B-Instruct | 10-60-205-41 (3080Ti) | 6GB | 8003 |
| 4 | vllm-qwen3-06b-3080ti | Qwen3-0.6B | 10-60-205-41 (3080Ti) | 6GB | 8004 |
| 5 | vllm-qwen3-06b-2080 | Qwen3-0.6B | 10-60-10-196 (2080) | 4GB | 8006 |
| 6 | vllm-qwen25-05b-3090-2 | Qwen2.5-0.5B-Instruct | 10-60-18-8 (3090) | 6GB | 8007 |
| 7 | vllm-qwen3-06b-3090-2 | Qwen3-0.6B | 10-60-18-8 (3090) | 6GB | 8008 |
5.3 4GB vGPU 完整 YAML (RTX 2080)
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-qwen3-06b-2080
spec:
replicas: 1
selector:
matchLabels:
app: vllm-qwen3-06b-2080
template:
metadata:
labels:
app: vllm-qwen3-06b-2080
spec:
schedulerName: hami-scheduler
nodeSelector:
kubernetes.io/hostname: "10-60-10-196"
containers:
- name: vllm
image: 117.50.188.237:30000/vllm/vllm-openai:v0.8.4
imagePullPolicy: IfNotPresent
args:
- --model
- /models/Qwen/Qwen3-0.6B
- --served-model-name
- qwen3-0.6b
- --port
- "8000"
- --device
- cuda
- --dtype
- float16
- --max-model-len
- "2048"
- --enforce-eager
- --max-num-seqs
- "4"
- --gpu-memory-utilization
- "0.95"
- --swap-space
- "0"
ports:
- containerPort: 8000
env:
- name: HF_ENDPOINT
value: "https://hf-mirror.com"
resources:
requests:
cpu: "500m"
memory: "2Gi"
nvidia.com/gpu: "1"
nvidia.com/gpumem: "4k"
limits:
memory: "4Gi"
nvidia.com/gpu: "1"
nvidia.com/gpumem: "4k"
volumeMounts:
- name: models
mountPath: /models
readOnly: true
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 10
volumes:
- name: models
persistentVolumeClaim:
claimName: nfs-modelscope
---
apiVersion: v1
kind: Service
metadata:
name: vllm-qwen3-06b-2080
spec:
type: ClusterIP
selector:
app: vllm-qwen3-06b-2080
ports:
- port: 8006
targetPort: 80005.4 部署与验证
bash
# 批量部署
kubectl apply -f vllm-qwen25-05b.yaml # 3090, :8001
kubectl apply -f vllm-qwen3-06b.yaml # 3090, :8002
kubectl apply -f vllm-qwen25-05b-3080ti.yaml # 3080Ti, :8003
kubectl apply -f vllm-qwen3-06b-3080ti.yaml # 3080Ti, :8004
kubectl apply -f vllm-qwen3-06b-2080.yaml # 2080, :8006
kubectl apply -f vllm-qwen25-05b-3090-2.yaml # 3090, :8007
kubectl apply -f vllm-qwen3-06b-3090-2.yaml # 3090, :8008
# 验证
kubectl get pods -o wide | grep vllm
kubectl run curl-test --rm -it --image=curlimages/curl -- \
curl -s http://vllm-qwen3-06b:8002/v1/models6. 参数详解
6.1 vLLM 启动参数
| 参数 | 默认值 | 说明 | 本集群值 |
|---|---|---|---|
--model | - | 模型路径(本地或 HuggingFace ID) | /models/Qwen/... |
--served-model-name | 同 model | API 中显示的模型名 | qwen2.5-0.5b / qwen3-0.6b |
--port | 8000 | HTTP 监听端口 | 8000 |
--device | auto | 计算设备:cuda / cpu / tpu | cuda |
--dtype | auto | 数据类型:float16 / bfloat16 / auto | float16 |
--max-model-len | 模型最大 | 最大上下文长度 | 2048 |
--enforce-eager | false | 禁用 CUDA graph(省显存但慢 5-10%) | 启用 |
--max-num-seqs | 256 | 最大并发请求数 | 4 |
--gpu-memory-utilization | 0.9 | GPU 显存使用比例 | 0.95 |
--swap-space | 4 | CPU swap 空间(GB),0=禁用 | 0 |
--tensor-parallel-size | 1 | 张量并行 GPU 数 | 1(单卡) |
6.2 关键决策说明
为什么用 float16 而不是 bfloat16?
RTX 2080: compute capability 7.5 → 不支持 bfloat16
RTX 3080 Ti: compute capability 8.6 → 支持
RTX 3090: compute capability 8.6 → 支持
为统一所有节点,全部使用 float16为什么 --enforce-eager?
CUDA graph 会为每个 batch size 缓存一个计算图,在显存受限时(vGPU 6GB)容易导致 OOM。禁用后节省 ~500MB-1GB 显存。
为什么 --max-num-seqs 4?
每个并发序列需要独立的 KV Cache。在 6GB vGPU 中,模型本身占用 ~1.5-4GB,剩余显存只够 4 个并发序列的 KV Cache。
7. API 使用指南
7.1 查看模型列表
bash
curl http://vllm-qwen3-06b:8002/v1/models | python3 -m json.tool
# 输出:
# {
# "object": "list",
# "data": [
# {
# "id": "qwen3-0.6b",
# "object": "model",
# "owned_by": "vllm"
# }
# ]
# }7.2 Chat Completions
bash
curl http://vllm-qwen3-06b:8002/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-0.6b",
"messages": [
{"role": "system", "content": "你是一个有帮助的助手。"},
{"role": "user", "content": "解释什么是 Kubernetes"}
],
"temperature": 0.7,
"max_tokens": 256
}'7.3 Streaming 响应
bash
curl http://vllm-qwen3-06b:8002/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-0.6b",
"messages": [{"role": "user", "content": "写一首关于春天的诗"}],
"stream": true
}'7.4 Python 客户端
python
from openai import OpenAI
client = OpenAI(
base_url="http://vllm-qwen3-06b:8002/v1",
api_key="not-needed"
)
response = client.chat.completions.create(
model="qwen3-0.6b",
messages=[
{"role": "system", "content": "你是一个有帮助的助手。"},
{"role": "user", "content": "Python 中如何实现快速排序?"}
],
temperature=0.7,
max_tokens=512
)
print(response.choices[0].message.content)7.5 从集群外部访问
通过 Traefik Ingress(路径 /api/qwen3):
bash
curl http://117.50.188.237/api/qwen3/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-0.6b",
"messages": [{"role": "user", "content": "你好"}],
"max_tokens": 100
}'8. 性能调优
8.1 显存优化
| 参数 | 效果 | 适用场景 |
|---|---|---|
--enforce-eager | 节省 ~500MB-1GB | 显存紧张时必选 |
--max-model-len 1024 | 减少 KV Cache | 短文本场景 |
--max-num-seqs 2 | 减少并发 KV Cache | 单用户场景 |
--gpu-memory-utilization 0.98 | 允许更多显存 | 独占 vGPU |
--swap-space 0 | 禁用 CPU swap | 避免 OOM killer |
8.2 吞吐量优化
| 参数 | 效果 | 适用场景 |
|---|---|---|
--max-num-seqs 32 | 增加并发 | 显存充足 |
--enable-chunked-prefill | 分块预填充 | 长文本 |
--disable-log-requests | 减少日志 IO | 生产环境 |
--block-size 32 | 优化 KV Cache 页大小 | 大 batch |
8.3 模型量化
使用 GPTQ/AWQ 量化模型可显著降低显存需求:
bash
# 下载量化模型
python3 -c "
from modelscope import snapshot_download
snapshot_download('Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4',
cache_dir='/model/ModelScope/Qwen')
"量化模型显存需求参考:
| 模型 | FP16 | INT4 量化 | INT8 量化 |
|---|---|---|---|
| Qwen2.5-0.5B | ~1.1GB | ~0.4GB | ~0.6GB |
| Qwen3-0.6B | ~1.2GB | ~0.5GB | ~0.7GB |
| Qwen2.5-7B | ~14GB | ~4.5GB | ~7.5GB |
| Qwen2.5-14B | ~28GB | ~9GB | ~15GB |
9. 故障排查
9.1 常见错误
CUDA Out of Memory
torch.cuda.OutOfMemoryError: CUDA out of memory.解决:
bash
--max-model-len 1024 # 降低上下文长度
--max-num-seqs 2 # 降低并发
--gpu-memory-utilization 0.90 # 降低利用率bfloat16 not supported
ValueError: The current device does not support bfloat16解决:添加 --dtype float16
Model not found (HuggingFace)
OSError: We couldn't connect to 'https://huggingface.co'解决:
yaml
env:
- name: HF_ENDPOINT
value: "https://hf-mirror.com"9.2 健康检查
bash
# 检查 vLLM 健康状态
kubectl exec -it <pod-name> -- curl -s http://localhost:8000/health
# 检查 GPU 使用情况
kubectl exec -it <pod-name> -- nvidia-smi
# 查看日志
kubectl logs -f deploy/vllm-qwen3-06b9.3 性能监控
bash
# 实时监控 GPU
watch -n 1 "kubectl exec <pod-name> -- nvidia-smi"
# 查看推理延迟
time curl -s http://vllm-qwen3-06b:8002/v1/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen3-0.6b","prompt":"Hello","max_tokens":10}'
# 查看 vLLM 内部指标
curl -s http://vllm-qwen3-06b:8002/metrics | head -30附录
A. 支持的模型架构
| 架构 | 示例模型 |
|---|---|
| LlamaForCausalLM | LLaMA, LLaMA-2, LLaMA-3 |
| Qwen2ForCausalLM | Qwen2, Qwen2.5 |
| Qwen3ForCausalLM | Qwen3 |
| MistralForCausalLM | Mistral, Mixtral |
| ChatGLMModel | ChatGLM-3, GLM-4 |
| PhiForCausalLM | Phi-2, Phi-3 |
| InternLMForCausalLM | InternLM, InternLM2 |
B. 显存计算公式
总显存 = 模型权重 + KV Cache + 激活值 + 框架开销
模型权重 ≈ 参数量 × 2 bytes (FP16)
KV Cache ≈ 2 × 层数 × hidden_dim × seq_len × batch_size × 2 bytes
激活值 ≈ batch_size × seq_len × hidden_dim × 2 bytes
框架开销 ≈ 500MB - 1GB文档版本: v1.0
更新时间: 2026-08-22
适用版本: vLLM v0.8.4