文章总结: 本文详细介绍了vLLM在生产环境部署OpenAI兼容推理服务的完整流程,强调不能仅靠单条启动命令。核心要点包括:确定服务边界(vLLM负责推理,Nginx提供入口)、检查主机GPU与容器运行时、验证模型目录完整性、确认镜像参数、以前台方式最小启动、使用DockerCompose固化部署、逐层验证API(健康检查、模型列表、非流式与流式请求)、用SDK验证兼容性、处理聊天模板与Base模型、以及进行并发与显存基线测试。文章提供了大量可执行的bash脚本和配置示例,并指出了常见陷阱如健康通过不代表推理正确、gpu-memory-utilization过高可能导致OOM等。 综合评分: 87 文章分类: AI安全,安全工具,技术标准,解决方案
vLLM 部署实战:搭建 OpenAI 兼容推理服务
点击关注 👉 点击关注 👉
马哥Linux运维
2026年7月19日 18:00 广东
在小说阅读器读本章
去阅读
vLLM 部署实战:搭建 OpenAI 兼容推理服务
vLLM 能快速把本地模型转换为 OpenAI 兼容 API,但生产部署不能只停留在一条启动命令。驱动与镜像是否兼容、模型文件是否完整、KV Cache 如何规划、并发是否超过显存边界、流式响应是否被代理缓存、故障能否定位、版本能否回滚,都会决定服务是否真正可用。
本文以 Linux、NVIDIA GPU、Docker Compose 和 vllm serve 为主。<模型目录>、
一、先确定服务边界
vLLM 负责模型加载、批处理、KV Cache 和推理接口,不应直接承担公网 TLS、企业认证、租户配额和跨实例负载均衡。通常让 vLLM 监听回环或内网地址,由 Nginx/API Gateway 提供统一入口。
上线前确认模型精度、最大上下文、GPU 数量、张量并行度、最大并发、输入输出上限、模型逻辑名、聊天模板和访问范围。没有这些边界,显存与并发参数无法合理配置。
二、检查主机、GPU 与容器运行时
bash
#!/usr/bin/env bash
set -euo pipefail
MODEL_DIR="<模型目录>"
nvidia-smi --query-gpu=index,uuid,name,driver_version,memory.total,memory.used --format=csv
docker version
docker compose version
df -h "$MODEL_DIR"
du -sh "$MODEL_DIR"
宿主机 nvidia-smi 成功不代表容器能访问 GPU。使用企业已验证的 CUDA 镜像做最小验证。
bash
docker run --rm --gpus all <受信任CUDA镜像> nvidia-smi --query-gpu=index,uuid,name,driver_version --format=csv
容器失败时优先检查 NVIDIA Container Toolkit、Docker device request 和守护进程日志,不要先修改 vLLM 参数。
三、验证模型目录
bash
MODEL_DIR="<模型目录>"
test -r "$MODEL_DIR/config.json"
find "$MODEL_DIR" -maxdepth 1 -type f \( -name '*.safetensors' -o -name '*.safetensors.index.json' -o -name 'tokenizer.json' -o -name 'tokenizer_config.json' \) -printf '%f\n' | sort
读取模型架构、dtype 和上下文配置,确认没有指向错误目录。
bash
jq '{architectures,model_type,torch_dtype,max_position_embeddings}' <模型目录>/config.json
jq '{model_max_length,chat_template}' <模型目录>/tokenizer_config.json
findmnt -T <模型目录> -o TARGET,SOURCE,FSTYPE,OPTIONS
共享存储加载慢时,应结合 iostat、存储吞吐和容器日志判断;GPU 利用率低并不等于模型进程卡死。
四、确认镜像和参数
bash
IMAGE="<vLLM镜像>:<vLLM镜像标签>"
docker image inspect "$IMAGE" --format 'Id={{.Id}} Digests={{json .RepoDigests}}'
docker run --rm --entrypoint vllm "$IMAGE" --version
docker run --rm --entrypoint vllm "$IMAGE" serve --help | less
重点确认 host、port、served-model-name、tensor-parallel-size、dtype、max-model-len、gpu-memory-utilization 和 max-num-seqs。参数不存在时应按当前版本替换,不能混用不同版本命令。
五、以前台方式最小启动
以下示例使用 GPU 0、1,TP 为 2,模型以 BF16 加载。GPU 数量必须与 TP 一致,模型与硬件必须支持所选 dtype。
bash
docker run --rm --gpus '"device=0,1"' --ipc=host --shm-size=32g \
-p 8000:8000 -v "<模型目录>:/models/model:ro" \
--entrypoint vllm <vLLM镜像>:<vLLM镜像标签> \
serve /models/model \
--served-model-name <对外模型名> --host 0.0.0.0 --port 8000 \
--tensor-parallel-size 2 --dtype bfloat16 --max-model-len 8192 \
--gpu-memory-utilization 0.85 --max-num-seqs 32
gpu-memory-utilization 影响模型与 KV Cache 的显存规划,不是“业务最多用多少显存”的绝对限制。值过高可能在 CUDA Graph、通信缓冲或峰值请求时 OOM。trust-remote-code 会执行模型仓库代码,只有经过审查且模型确实要求时才启用。
六、使用 Compose 固化部署
yaml
services:
vllm-api:
image: <vLLM镜像>:<vLLM镜像标签>
container_name: vllm_api_8000
restart: unless-stopped
ipc: host
shm_size: 32g
ports:
- "127.0.0.1:8000:8000"
environment:
CUDA_VISIBLE_DEVICES: "0,1"
volumes:
- <模型目录>:/models/model:ro
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["0", "1"]
capabilities: [gpu]
entrypoint: ["vllm", "serve"]
command:
- /models/model
- --served-model-name
- <对外模型名>
- --host
- 0.0.0.0
- --port
- "8000"
- --tensor-parallel-size
- "2"
- --dtype
- bfloat16
- --max-model-len
- "8192"
- --gpu-memory-utilization
- "0.85"
- --max-num-seqs
- "32"
healthcheck:
test: ["CMD-SHELL", "python3 -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)\""]
interval: 30s
timeout: 5s
retries: 5
start_period: 600s
logging:
driver: json-file
options:
max-size: 100m
max-file: "5"
启动前渲染配置、检查端口和 GPU 占用。Compose 子命令使用 service 名 vllm-api,不是 container_name。
bash
COMPOSE_FILE="<Compose文件路径>"
docker compose -f "$COMPOSE_FILE" config
ss -lntp | grep ':8000 ' || true
nvidia-smi --query-compute-apps=gpu_uuid,pid,process_name,used_memory --format=csv || true
bash
docker compose -f <Compose文件路径> up -d vllm-api
docker compose -f <Compose文件路径> ps vllm-api
docker compose -f <Compose文件路径> logs -f --tail=300 vllm-api
七、逐层验证 API
先确认监听和健康端点。健康通过只代表进程可响应,不代表推理正确。
bash
ss -lntp | grep ':8000 '
curl -fsS --connect-timeout 2 --max-time 10 http://127.0.0.1:8000/health
确认模型列表中的 ID 与 served-model-name 相同。
bash
curl -fsS http://127.0.0.1:8000/v1/models | jq .
非流式 Chat Completions 用于验证响应结构、finish_reason 和 usage。
bash
curl -fsS http://127.0.0.1:8000/v1/chat/completions -H 'Content-Type: application/json' -d '{
"model":"<对外模型名>",
"messages":[{"role":"user","content":"只回复 ready"}],
"temperature":0,
"max_tokens":16,
"stream":false
}' | jq .
流式请求使用 curl -N,确认数据逐段到达而不是被中间代理缓存。
bash
curl -N -fsS http://127.0.0.1:8000/v1/chat/completions -H 'Content-Type: application/json' -d '{
"model":"<对外模型名>",
"messages":[{"role":"user","content":"列出三项上线检查。"}],
"temperature":0.2,
"max_tokens":128,
"stream":true
}'
八、用 SDK 验证兼容性
python
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("LLM_BASE_URL", "http://127.0.0.1:8000/v1"),
api_key=os.environ.get("LLM_API_KEY", "local-not-checked"),
)
response = client.chat.completions.create(
model="<对外模型名>",
messages=[{"role": "user", "content": "返回当前请求是否成功。"}],
temperature=0,
max_tokens=64,
)
print(response.choices[0].message.content)
API Key 应由环境变量或密钥系统注入,不应写入仓库。验收还要覆盖超长输入、错误结构、流式结束、客户端中断和并发行为。
九、聊天模板与 Base 模型
Base 模型或 tokenizer 缺失 chat_template 时,Chat Completions 可能启动失败或格式错误。模板必须来自模型官方或内部验证版本,并纳入版本控制。
bash
jq -r '.chat_template // "NO_CHAT_TEMPLATE"' <模型目录>/tokenizer_config.json
sha256sum <聊天模板文件>
修改模板会改变全部真实 prompt,属于模型行为变更,必须回归测试并保留旧模板回滚。
十、并发与显存基线
max-model-len 越大,单请求潜在 KV Cache 越高;max-num-seqs 越大,并发能力和排队行为变化。以下脚本只做短请求稳定性检查,不替代专业基准。
bash
#!/usr/bin/env bash
set -euo pipefail
URL="http://127.0.0.1:8000/v1/chat/completions"
MODEL="<对外模型名>"
TOTAL="32"
CONCURRENCY="8"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
request_one() {
id="$1"
curl -sS -o "$TMP_DIR/$id.json" -w "id=$id code=%{http_code} total=%{time_total}\n" -H 'Content-Type: application/json' -d "{\"model\":\"$MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"返回编号 $id\"}],\"temperature\":0,\"max_tokens\":32}" "$URL"
}
export -f request_one
export URL MODEL TMP_DIR
seq 1 "$TOTAL" | xargs -P "$CONCURRENCY" -I{} bash -c 'request_one "$@"' _ {}
压测时同步采集 GPU 和服务指标。vLLM Prometheus 指标名称以实际服务暴露为准,不同版本前缀与标签可能变化。
bash
nvidia-smi dmon -s pucvmet -d 1 -o DT
curl -fsS http://127.0.0.1:8000/metrics | sed -n '1,100p'
吞吐不再上升而排队时延持续增加,说明实例越过合理并发边界,应限流或扩实例,而不是继续增大 max-num-seqs。
十一、启动失败与 OOM
容器退出时先看退出码、OOM 标志、日志和实际命令,不要反复重启覆盖首个错误。
bash
CONTAINER="vllm_api_8000"
docker inspect "$CONTAINER" --format 'Status={{.State.Status}} Exit={{.State.ExitCode}} OOM={{.State.OOMKilled}} Error={{.State.Error}}'
docker logs --timestamps --tail=400 "$CONTAINER"
docker inspect "$CONTAINER" --format '{{json .Config.Cmd}}' | jq .
CUDA OOM 时核对每张卡的全部进程和容器映射。
bash
nvidia-smi --query-gpu=index,uuid,memory.total,memory.used,memory.free --format=csv
nvidia-smi --query-compute-apps=gpu_uuid,pid,process_name,used_memory --format=csv
docker inspect vllm_api_8000 --format '{{json .HostConfig.DeviceRequests}}' | jq .
降低 gpu-memory-utilization、max-model-len 或 max-num-seqs时一次只改一个变量,并重新完成同样压测。
十二、多卡与 NCCL 排障
多卡初始化卡住时检查 TP、可见 GPU、拓扑、进程与 Xid。
bash
nvidia-smi topo -m
ps -eo pid,ppid,stat,etime,cmd | grep -E '[v]llm|[t]orch'
journalctl -k --since '-30 min' --no-pager | grep -Ei 'NVRM|Xid|nvlink|pcie|oom' || true
NCCL 调试只在复现窗口临时启用,避免长期产生大量日志。
bash
NCCL_DEBUG=INFO NCCL_DEBUG_SUBSYS=INIT,GRAPH CUDA_VISIBLE_DEVICES=0,1 vllm serve <模型目录> --tensor-parallel-size 2 --served-model-name <对外模型名> --port 8000
十三、通过 Nginx 暴露服务
SSE 流式响应必须关闭代理缓冲,读取超时应覆盖业务最长生成时间。
nginx
upstream vllm_backend {
server 127.0.0.1:8000;
keepalive 64;
}
location /v1/ {
proxy_pass http://vllm_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Request-ID $request_id;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 3s;
proxy_send_timeout 60s;
proxy_read_timeout 600s;
proxy_request_buffering off;
proxy_buffering off;
gzip off;
}
配置修改采用备份、语法检查、reload、验证闭环。
bash
sudo cp -a <Nginx配置文件> <Nginx配置文件>.bak.$(date +%Y%m%d-%H%M%S)
sudo nginx -t
sudo systemctl reload nginx
curl -fsS https://<API域名>/v1/models | jq .
vLLM 端口不应直接暴露公网。鉴权、TLS、限流、请求体限制和审计应由受控网关承担,日志不要记录完整 prompt 和 Authorization。
十四、升级和回滚
bash
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="<备份目录>/vllm-$(date +%Y%m%d-%H%M%S)"
COMPOSE_FILE="<Compose文件路径>"
install -d -m 0700 "$BACKUP_DIR"
cp -a "$COMPOSE_FILE" "$BACKUP_DIR/"
docker compose -f "$COMPOSE_FILE" config > "$BACKUP_DIR/compose.rendered.yaml"
docker image inspect <vLLM镜像>:<旧镜像标签> > "$BACKUP_DIR/image.inspect.json"
sha256sum <模型目录>/config.json > "$BACKUP_DIR/model-config.sha256"
新版本应在新端口启动,完成非流式、流式、长上下文和灰度后切换。失败时先回切网关,再停止新实例。
bash
sudo cp -a <旧Nginx配置备份> <Nginx配置文件>
sudo nginx -t && sudo systemctl reload nginx
curl -fsS https://<API域名>/v1/models | jq .
docker compose -f <新版本Compose文件> stop vllm-api
停止容器会中断在途请求,因此应先摘流和排空。回滚成功的标准是入口、模型名、聊天模板、核心请求、流式输出、错误率和时延全部恢复。
十五、日常巡检
bash
#!/usr/bin/env bash
set -euo pipefail
CONTAINER="vllm_api_8000"
BASE_URL="http://127.0.0.1:8000"
EXPECTED_MODEL="<对外模型名>"
[[ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER")" == "true" ]]
curl -fsS --max-time 5 "$BASE_URL/health" >/dev/null
MODELS="$(curl -fsS --max-time 10 "$BASE_URL/v1/models")"
jq -e --arg model "$EXPECTED_MODEL" '.data[] | select(.id == $model)' <<<"$MODELS" >/dev/null
nvidia-smi --query-gpu=index,utilization.gpu,memory.used,memory.total,temperature.gpu --format=csv
自动重启前仍需区分模型加载慢、OOM、NCCL、Xid、网关故障与过载。可靠上线还要覆盖镜像 digest、只读模型、GPU/TP 一致、上下文与并发边界、SSE、鉴权、日志脱敏、监控、限流和回滚。
文末阅读福利
仅目前来说,无论是运维人转型提升,还是零基础想转行IT,最好的岗位就是云计算运维&SRE岗位。
为了帮助大家早日快速入门云计算运维领域,给大家整理了一套【最新运维资料】高级运维工程师必备技能资料包(文末一键免费领取),内容有多详实丰富看下图!
1.38张最全工程师技能图谱
2.面试大礼包
3.Linux书籍
内容比较多,就不一一展示了
以上所有资料获取请扫码:
识别上方二维码
备注:2026最新运维资料
100%免费领取
(是扫码领取,不是在公众号后台回复,别看错了哦)
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:马哥Linux运维 点击关注 👉 点击关注 👉《vLLM 部署实战:搭建 OpenAI 兼容推理服务》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。





![[AI]Claude+Skills自动漏洞挖掘](/images/random/titlepic/2.jpg)




评论