文档版本:v1.0
适用环境:Ubuntu 22.04 LTS / NVIDIA L20 (48GB) 及同类 NVIDIA IDC GPU 服务器
工程目录:/opt/llm-ops
目录
一、项目架构与环境清单
二、GPU 容器基础环境初始化
三、vLLM 大模型部署与核心参数调优解析
四、LiteLLM 网关、Open-WebUI 与 Nginx SSE 代理优化
五、Prometheus + Grafana + DCGM 全链路监控与钉钉告警
六、项目最终成果展示
七、日常运维与常见故障排查手册(SOP)
一、项目架构与环境清单
1.1 全栈系统拓扑图
1.2 软硬件版本明细表
| 分类 | 组件名称 | 生产实测规格 / 版本号 | 备注说明 |
|---|---|---|---|
| 云服务器规格 | 阿里云 ECS GPU 实例 | ecs.gn8is.4xlarge(华东 1 杭州) |
16 vCPU (Intel Xeon Gold 6462C),123 GiB RAM |
| GPU 硬件 | NVIDIA L20 | 单卡 46068 MiB (48GB 显存) |
PCIe Bus ID 00000000:00:03.0,TDP 350W |
| 操作系统 | Ubuntu 22.04.5 LTS | jammy (Kernel 5.15.0-198-generic) |
根分区 /dev/nvme0n1p3 197 GiB |
| GPU 驱动 | NVIDIA Server Driver | 580.178.04 (最高支持 CUDA 13.0) |
预编译内核模块 linux-modules-nvidia-580-server |
| CUDA 工具包 | CUDA Toolkit (nvcc) |
12.6 (V12.6.85) |
NVIDIA 中国官方 CDN 源安装 |
| 容器运行时 | Docker Engine & Compose | Docker 29.9.3 / Compose v5.7.0 |
阿里云内网 Docker CE 源安装 |
| GPU 容器工具 | NVIDIA Container Toolkit | 1.20.1 (nvidia-ctk) |
配置 nvidia runtime |
| 模型下载工具 | ModelScope Python SDK | modelscope 1.40.3 |
阿里云魔搭社区内网极速直连(~450 MB/s) |
| 推理引擎镜像 | vllm/vllm-openai |
v0.8.5.post1 |
开启 awq_marlin 算子与 deepseek_r1 思维链解析 |
| AI 网关镜像 | berriai/litellm |
main-latest |
统一暴露 OpenAI /v1/chat/completions 接口 |
| 交互前端镜像 | open-webui/open-webui |
main |
离线模式对接 LiteLLM |
| 反向代理镜像 | nginx |
alpine (nginx/1.31.8) |
HTTPS 终结与 SSE 无缓冲流式调优 |
| 监控告警组件 | DCGM / Prom / AM / Grafana | DCGM 3.3.8-3.6.0 / Prom v2.54.1 / AM v0.27.0 / Grafana 11.2.0 / DingTalk v2.1.0 |
全链路硬件+推理指标采集与钉钉告警 |
1.3 端口与目录规划表
1.3.1 服务端口映射表
| 容器名称 | 服务角色 | 宿主机监听地址与端口 | 容器内部端口 | 访问方式与用途说明 |
|---|---|---|---|---|
llmops-nginx |
HTTPS 反代网关 | 0.0.0.0:80 / 0.0.0.0:443 |
80 / 443 |
80 强制 301 跳转 443;/ 反代 WebUI,/v1/ 反代 LiteLLM |
litellm |
统一大模型路由网关 | 0.0.0.0:4000 |
4000 |
统一 OpenAI 兼容 API(Master Key: sk-llmops-master-key) |
open-webui |
Web 聊天交互界面 | 127.0.0.1:8080 |
8080 |
仅绑定本地回环,通过 Nginx :443 对外提供安全访问 |
vllm-deepseek |
DeepSeek-R1 7B 推理实例 | 127.0.0.1:8001 |
8000 |
内部推理接口与 /metrics 指标接口 |
vllm-qwen3 |
Qwen3 8B 推理实例 | 127.0.0.1:8002 |
8000 |
内部推理接口与 /metrics 指标接口 |
dcgm-exporter |
GPU 硬件指标导出器 | 0.0.0.0:9400 |
9400 |
暴露 /metrics GPU 显存、温度、利用率等 DCGM 指标 |
prometheus |
时序数据库与告警引擎 | 0.0.0.0:9090 |
9090 |
采集 DCGM 与双 vLLM 指标,评估告警规则 |
grafana |
可视化监控面板 | 0.0.0.0:3000 |
3000 |
默认账号密码 admin / admin,已预置 Prometheus 数据源 |
alertmanager |
告警路由与静默管理 | 0.0.0.0:9093 |
9093 |
接收 Prometheus 告警并路由至钉钉 Webhook 插件 |
dingtalk-webhook |
钉钉机器人转发器 | 0.0.0.0:8060 |
8060 |
接收 Alertmanager Webhook 并格式化推送至钉钉群 |
1.3.2 宿主机目录结构规划 (/opt/llm-ops)
/opt/llm-ops/
├── docker-compose.yml # 10 服务全栈容器编排文件
├── verify_stage2_3.sh # 流式推理与网关验证脚本
├── verify_stage4.sh # 监控指标与告警规则验证脚本
├── download_models.py # ModelScope 模型权重直连高速下载脚本
├── models/ # 大模型权重持久化目录
│ ├── DeepSeek-R1-Distill-Qwen-7B-AWQ/ # DeepSeek-R1 7B AWQ 4-bit 权重 (5.2 GiB)
│ └── Qwen3-8B-AWQ/ # Qwen3 8B AWQ 4-bit 权重 (5.7 GiB)
├── litellm/
│ └── config.yaml # LiteLLM 双模型路由与鉴权配置
├── nginx/
│ ├── nginx.conf # Nginx HTTPS 反代与 SSE 流式优化配置
│ └── ssl/
│ ├── server.crt # SSL 证书
│ └── server.key # SSL 私钥
├── open-webui/
│ └── data/ # Open-WebUI 数据库与会话持久化目录
└── monitoring/
├── prometheus/
│ ├── prometheus.yml # Prometheus 采集目标与 Alertmanager 配置
│ └── alert_rules.yml # 4 条核心 GPU 与 vLLM 告警规则
├── alertmanager/
│ └── alertmanager.yml # Alertmanager 路由配置
├── dingtalk/
│ └── config.yml # 钉钉机器人 Webhook 与加签配置
└── grafana/
└── provisioning/
└── datasources/
└── datasource.yml # Grafana 自动注入 Prometheus 数据源配置
二、GPU 容器基础环境初始化
2.1 硬件与系统基线探测
在裸机部署前,执行以下命令确认系统版本、内核头文件、GPU PCIe 设备以及磁盘空间:
# 1. 查看系统版本与内核版本
lsb_release -a
uname -r
# 2. 检查 NVIDIA GPU PCIe 设备与 nouveau 模块状态
lspci | grep -i nvidia
lsmod | grep -iE "nouveau|nvidia" || echo "No conflicting nouveau module loaded"
# 3. 检查 CPU、内存与磁盘空间
lscpu | grep -E "Model name|^CPU\(s\):"
free -h
df -h
实测探测输出:
Distributor ID: Ubuntu
Description: Ubuntu 22.04.5 LTS
Release: 22.04
Codename: jammy
Kernel: 5.15.0-198-generic
GPU: 00:03.0 3D controller: NVIDIA Corporation Device 26ba (rev a1) [NVIDIA L20]
CPU: 16 vCPU (Intel(R) Xeon(R) Gold 6462C)
Memory: 123Gi total, 122Gi available
Disk (/): 197G total, 3.2G used, 186G available (2%)
2.2 配置 APT 全局直连与国内高速软件源
若服务器处于配置了 SSH 隧道代理(如 127.0.0.1:1080)的环境中,为保护隧道带宽并确保 APT 100% 走阿里云内网及国内高速镜像源,首先创建 /etc/apt/apt.conf.d/99no-proxy:
cat << 'EOF' > /etc/apt/apt.conf.d/99no-proxy
Acquire::http::Proxy "false";
Acquire::https::Proxy "false";
EOF
随后配置 NVIDIA CUDA 中国官方 CDN 源、阿里云内网 Docker CE 源 与 中科大 NVIDIA Container Toolkit 源:
# 1. 配置 NVIDIA CUDA 中国官方 CDN 源 (developer.download.nvidia.cn)
curl --noproxy '*' -fsSL https://developer.download.nvidia.cn/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb -o /tmp/cuda-keyring.deb
dpkg -i /tmp/cuda-keyring.deb
sed -i 's/developer.download.nvidia.com/developer.download.nvidia.cn/g' /etc/apt/sources.list.d/cuda-ubuntu2204-x86_64.list
# 2. 配置阿里云内网 Docker CE 源 (mirrors.cloud.aliyuncs.com)
install -m 0755 -d /etc/apt/keyrings
curl --noproxy '*' -fsSL http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
cat << 'EOF' > /etc/apt/sources.list.d/docker.list
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] http://mirrors.cloud.aliyuncs.com/docker-ce/linux/ubuntu jammy stable
EOF
# 3. 配置中科大 NVIDIA Container Toolkit 镜像源 (mirrors.ustc.edu.cn)
curl --noproxy '*' -fsSL https://mirrors.ustc.edu.cn/libnvidia-container/gpgkey | gpg --dearmor --yes -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl --noproxy '*' -s -L https://mirrors.ustc.edu.cn/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://nvidia.github.io/libnvidia-container/stable/deb/#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://mirrors.ustc.edu.cn/libnvidia-container/stable/deb/#g' > /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 4. 更新软件源索引
apt-get update
2.3 安装 NVIDIA 驱动与 CUDA Toolkit 12.6
优先选用 Ubuntu 官方仓库中与当前内核(5.15.0-198-generic)精确匹配的预编译驱动模块包 linux-modules-nvidia-580-server-$(uname -r) 与 nvidia-driver-580-server,无需重启操作系统即可直接通过 modprobe 加载内核模块:
# 1. 安装 NVIDIA 580 Server 驱动与预编译内核模块
DEBIAN_FRONTEND=noninteractive apt-get install -y \
linux-modules-nvidia-580-server-$(uname -r) \
nvidia-driver-580-server
# 2. 加载内核模块并验证 nvidia-smi
modprobe nvidia
modprobe nvidia-uvm
nvidia-smi
# 3. 安装 CUDA Toolkit 12.6 并配置全局环境变量
DEBIAN_FRONTEND=noninteractive apt-get install -y cuda-toolkit-12-6
cat << 'EOF' > /etc/profile.d/cuda.sh
export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
EOF
chmod +x /etc/profile.d/cuda.sh
source /etc/profile.d/cuda.sh
nvcc --version
实测验证输出:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.178.04 Driver Version: 580.178.04 CUDA Version: 13.0 |
+-----------------------------------------+------------------------+----------------------+
| 0 NVIDIA L20 Off | 00000000:00:03.0 Off | 0 |
| N/A 33C P0 82W / 350W | 0MiB / 46068MiB | 0% Default |
+-----------------------------------------+------------------------+----------------------+
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2024 NVIDIA Corporation
Built on Tue_Oct_29_23:50:19_PDT_2024
Cuda compilation tools, release 12.6, V12.6.85
Build cuda_12.6.r12.6/compiler.35059454_0
2.4 安装 Docker 与 NVIDIA Container Toolkit 并完成闭环验证
# 1. 安装 Docker Engine、Compose 插件与 NVIDIA Container Toolkit
DEBIAN_FRONTEND=noninteractive apt-get install -y \
docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \
nvidia-container-toolkit
# 2. 生成 NVIDIA Container Runtime 配置并写入国内镜像加速源
nvidia-ctk runtime configure --runtime=docker
cat << 'EOF' > /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
],
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
EOF
# 3. 启动并设置 Docker 开机自启
systemctl daemon-reload
systemctl enable --now docker
systemctl restart docker
# 4. 运行最小化容器验证容器内 GPU 识别闭环
docker run --rm --gpus all docker.m.daocloud.io/library/ubuntu:22.04 nvidia-smi
三、vLLM 大模型部署与核心参数调优解析
3.1 使用 ModelScope 高速下载 AWQ 4-bit 量化模型
针对单卡 NVIDIA L20 (48GB 显存) 同时部署两个 7B/8B 级别推理模型的场景,选用 4-bit AWQ 量化权重(每个模型权重仅占 5.2 ~ 5.7 GiB),通过阿里云魔搭社区(ModelScope)内网直连下载:
# 1. 使用阿里云内网 PyPI 源安装 modelscope
pip3 install --no-cache-dir -U modelscope \
-i http://mirrors.cloud.aliyuncs.com/pypi/simple/ \
--trusted-host mirrors.cloud.aliyuncs.com
# 2. 编写下载脚本 /opt/llm-ops/download_models.py
cat << 'EOF' > /opt/llm-ops/download_models.py
#!/usr/bin/env python3
import os
import time
# 强制清空代理环境变量,确保 100% 走阿里云魔搭社区直连高速下载
for k in ["http_proxy", "https_proxy", "all_proxy", "HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY"]:
os.environ.pop(k, None)
from modelscope import snapshot_download
MODELS = [
{
"repo_id": "AngelSlim/Deepseek_r1_distill_qwen-7b_int4_awq",
"local_dir": "/opt/llm-ops/models/DeepSeek-R1-Distill-Qwen-7B-AWQ",
},
{
"repo_id": "Qwen/Qwen3-8B-AWQ",
"local_dir": "/opt/llm-ops/models/Qwen3-8B-AWQ",
},
]
def main():
os.makedirs("/opt/llm-ops/models", exist_ok=True)
for m in MODELS:
t0 = time.time()
print(f"=== Start downloading {m['repo_id']} -> {m['local_dir']} ===", flush=True)
path = snapshot_download(
model_id=m["repo_id"],
local_dir=m["local_dir"],
max_workers=8,
)
elapsed = time.time() - t0
print(f"=== Finished {m['repo_id']} in {elapsed:.1f}s at {path} ===", flush=True)
if __name__ == "__main__":
main()
EOF
# 3. 执行下载并校验权重文件
python3 /opt/llm-ops/download_models.py
ls -lh /opt/llm-ops/models/DeepSeek-R1-Distill-Qwen-7B-AWQ /opt/llm-ops/models/Qwen3-8B-AWQ
3.2 完整生产级 docker-compose.yml(含双 vLLM + 网关 + 监控栈)
将以下完整内容保存至 /opt/llm-ops/docker-compose.yml:
services:
# ============================================================================
# 服务 1:vLLM 推理实例 - DeepSeek-R1-Distill-Qwen-7B-AWQ (内部端口 8001)
# ============================================================================
# 【多卡张量并行 (Tensor Parallelism) 扩展配置说明】:
# 当前机器为单卡 NVIDIA L20 (48GB),因此设置 --tensor-parallel-size 1。
# 若在多卡服务器(如 2 卡、4 卡或 8 卡)上部署更大尺寸模型(如 32B/70B),请修改:
# 1. 将 --tensor-parallel-size 设置为实际使用的 GPU 卡数(如 --tensor-parallel-size 2 或 4)
# 2. 在 environment 中指定可见卡号(如 NVIDIA_VISIBLE_DEVICES=0,1)及通信优化变量(如 NCCL_P2P_DISABLE=0)
# 3. 增大共享内存 shm_size(如 shm_size: "16g")以支撑多进程 NCCL 高速通信
vllm-deepseek:
image: docker.m.daocloud.io/vllm/vllm-openai:v0.8.5.post1
container_name: vllm-deepseek
restart: unless-stopped
ipc: host
shm_size: "8g"
ports:
- "127.0.0.1:8001:8000"
volumes:
- /opt/llm-ops/models:/models:ro
environment:
- NVIDIA_VISIBLE_DEVICES=all
- VLLM_NO_USAGE_STATS=1
- VLLM_USE_V1=0
command:
- "--model"
- "/models/DeepSeek-R1-Distill-Qwen-7B-AWQ"
- "--served-model-name"
- "DeepSeek-R1-Distill-Qwen-7B-AWQ"
- "--host"
- "0.0.0.0"
- "--port"
- "8000"
- "--quantization"
- "awq_marlin"
- "--dtype"
- "half"
- "--gpu-memory-utilization"
- "0.42"
- "--max-num-seqs"
- "32"
- "--max-model-len"
- "16384"
- "--tensor-parallel-size"
- "1"
- "--enable-reasoning"
- "--reasoning-parser"
- "deepseek_r1"
- "--enable-auto-tool-choice"
- "--tool-call-parser"
- "hermes"
- "--show-hidden-metrics-for-version"
- "0.8"
- "--trust-remote-code"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
- llmops-net
# ============================================================================
# 服务 2:vLLM 推理实例 - Qwen3-8B-AWQ (内部端口 8002)
# ============================================================================
# 【多卡张量并行说明】:单卡与 vllm-deepseek 共存各占 0.42 显存配额;
# 多卡部署时同样可通过调整 --tensor-parallel-size 2/4/8 与 NVIDIA_VISIBLE_DEVICES 扩展。
vllm-qwen3:
image: docker.m.daocloud.io/vllm/vllm-openai:v0.8.5.post1
container_name: vllm-qwen3
restart: unless-stopped
ipc: host
shm_size: "8g"
ports:
- "127.0.0.1:8002:8000"
volumes:
- /opt/llm-ops/models:/models:ro
environment:
- NVIDIA_VISIBLE_DEVICES=all
- VLLM_NO_USAGE_STATS=1
- VLLM_USE_V1=0
command:
- "--model"
- "/models/Qwen3-8B-AWQ"
- "--served-model-name"
- "Qwen3-8B-AWQ"
- "--host"
- "0.0.0.0"
- "--port"
- "8000"
- "--quantization"
- "awq_marlin"
- "--dtype"
- "half"
- "--gpu-memory-utilization"
- "0.42"
- "--max-num-seqs"
- "32"
- "--max-model-len"
- "16384"
- "--tensor-parallel-size"
- "1"
- "--enable-reasoning"
- "--reasoning-parser"
- "deepseek_r1"
- "--enable-auto-tool-choice"
- "--tool-call-parser"
- "hermes"
- "--show-hidden-metrics-for-version"
- "0.8"
- "--trust-remote-code"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
- llmops-net
# ============================================================================
# 服务 3:LiteLLM 统一网关 (端口 4000)
# ============================================================================
litellm:
image: ghcr.m.daocloud.io/berriai/litellm:main-latest
container_name: litellm
restart: unless-stopped
ports:
- "4000:4000"
volumes:
- /opt/llm-ops/litellm/config.yaml:/app/config.yaml:ro
environment:
- LITELLM_DROP_PARAMS=True
command:
- "--config"
- "/app/config.yaml"
- "--port"
- "4000"
- "--num_workers"
- "4"
depends_on:
- vllm-deepseek
- vllm-qwen3
networks:
- llmops-net
# ============================================================================
# 服务 4:Open-WebUI 交互前端 (内部端口 8080)
# ============================================================================
open-webui:
image: ghcr.m.daocloud.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
volumes:
- /opt/llm-ops/open-webui/data:/app/backend/data
environment:
- OPENAI_API_BASE_URL=http://litellm:4000/v1
- OPENAI_API_KEY=sk-llmops-master-key
- ENABLE_OLLAMA_API=false
- HF_HUB_OFFLINE=1
- SCARF_NO_ANALYTICS=true
- DO_NOT_TRACK=true
depends_on:
- litellm
networks:
- llmops-net
# ============================================================================
# 服务 5:Nginx HTTPS 反代与 SSE 流式调优网关 (端口 80 / 443)
# ============================================================================
nginx:
image: docker.m.daocloud.io/library/nginx:alpine
container_name: llmops-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /opt/llm-ops/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- /opt/llm-ops/nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- open-webui
- litellm
networks:
- llmops-net
# ============================================================================
# 服务 6:NVIDIA DCGM Exporter GPU 硬件指标采集 (端口 9400)
# ============================================================================
dcgm-exporter:
image: nvcr.m.daocloud.io/nvidia/k8s/dcgm-exporter:3.3.8-3.6.0-ubuntu22.04
container_name: dcgm-exporter
restart: unless-stopped
gpus: all
cap_add:
- SYS_ADMIN
ports:
- "9400:9400"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
- llmops-net
# ============================================================================
# 服务 7:Prometheus 监控指标采集与告警评估引擎 (端口 9090)
# ============================================================================
prometheus:
image: docker.m.daocloud.io/prom/prometheus:v2.54.1
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- /opt/llm-ops/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- /opt/llm-ops/monitoring/prometheus/alert_rules.yml:/etc/prometheus/alert_rules.yml:ro
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--web.enable-lifecycle"
depends_on:
- dcgm-exporter
networks:
- llmops-net
# ============================================================================
# 服务 8:Alertmanager 告警路由与静默中心 (端口 9093)
# ============================================================================
alertmanager:
image: docker.m.daocloud.io/prom/alertmanager:v0.27.0
container_name: alertmanager
restart: unless-stopped
ports:
- "9093:9093"
volumes:
- /opt/llm-ops/monitoring/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--storage.path=/alertmanager"
depends_on:
- dingtalk-webhook
networks:
- llmops-net
# ============================================================================
# 服务 9:Prometheus Webhook DingTalk 钉钉告警转发插件 (端口 8060)
# ============================================================================
dingtalk-webhook:
image: docker.m.daocloud.io/timonwong/prometheus-webhook-dingtalk:v2.1.0
container_name: dingtalk-webhook
restart: unless-stopped
ports:
- "8060:8060"
volumes:
- /opt/llm-ops/monitoring/dingtalk/config.yml:/etc/prometheus-webhook-dingtalk/config.yml:ro
command:
- "--config.file=/etc/prometheus-webhook-dingtalk/config.yml"
- "--web.listen-address=:8060"
networks:
- llmops-net
# ============================================================================
# 服务 10:Grafana 可观测性大盘 (端口 3000)
# ============================================================================
grafana:
image: docker.m.daocloud.io/grafana/grafana:11.2.0
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- /opt/llm-ops/monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
depends_on:
- prometheus
networks:
- llmops-net
networks:
llmops-net:
driver: bridge
3.3 vLLM 核心参数调优前后对比与底层机制深度解析
| 调优维度 | 参数项 | 默认值 (未调优) | 生产调优值 | 调优前后对比说明与工程原理解析 |
|---|---|---|---|---|
| 显存配额与多实例共存 | --gpu-memory-utilization+ VLLM_USE_V1=0 |
0.90 (VLLM_USE_V1=1) |
0.42 (VLLM_USE_V1=0) |
调优前:默认单实例抢占 90% 显存(41.4 GiB),且 vLLM 0.8.5 默认 V1 引擎在计算剩余可用显存时会扣除其他进程已用显存,导致第二实例启动直接报 ValueError: No available memory for the cache blocks。调优后:设置 0.42 并启用 V0 引擎(VLLM_USE_V1=0),双模型共存于单张 48GB L20 显卡,实测总显存占用稳定在 18297 MiB(约 39.7%),预留充足安全水位。 |
| 量化与算子加速 | --quantization |
无 (FP16/BF16) 或普通 awq |
awq_marlin (--dtype half) |
调优前:7B/8B FP16 权重需 15~16 GiB 显存;普通 awq 内核在 Batch 较大时受限于反量化开销。调优后:4-bit AWQ 权重仅占 5.2~5.7 GiB,且启用专为 Ampere/Ada (L20) 架构高度优化的 awq_marlin 算子,自动重排权重布局,使解码吞吐量提升 1.5~2.2 倍。 |
| 最大上下文长度 | --max-model-len |
模型默认值 (131072 / 40960) |
16384 |
调优前:默认按 128K/40K 预校验 KV Cache 容量,极易在 42% 显存配额下因 KV Cache 块不足而拒绝启动。 调优后:收敛至生产主流的 16384 (16K),使 vllm-deepseek 获得 3734 个 GPU 块(16K 并发度 3.65x),vllm-qwen3 获得 1154 个 GPU 块(16K 并发度 1.13x)。 |
| 并发序列上限 | --max-num-seqs |
256 |
32 |
调优前:默认 256 并发会在 CUDA Graph 捕获阶段与激活值峰值(Activation Peak Memory)占用额外数 GiB 显存,且高并发争抢导致 ITL(Token 间延迟)劣化。 调优后:设为 32,将 CUDA Graph 捕获耗时缩短至 3 秒(仅占 0.13~0.17 GiB),保障单请求生成流畅度。 |
| 张量并行度 | --tensor-parallel-size |
1 |
单卡 1(多卡设为 2/4/8) |
单卡场景:设为 1 避免任何跨卡通信开销。多卡扩展:部署 32B/70B 模型时,设为 GPU 数量(2 的幂次),配合 ipc: host、shm_size: "16g" 与 NVLink/PCIe P2P,将权重与 KV Cache 均匀切分至多张 GPU。 |
| 思维链结构化解析 | --enable-reasoning--reasoning-parser |
关闭(<think> 混入 content) |
deepseek_r1 |
调优前:模型输出的 <think>...</think> 原始标签直接混入 delta.content,前端难以区分思考过程与最终结论。调优后:引擎层流式状态机实时解析 <think> 标签,将推理过程放入标准字段 delta.reasoning_content,正文放入 delta.content。 |
四、LiteLLM 网关、Open-WebUI 与 Nginx SSE 代理优化
4.1 LiteLLM 统一网关配置 (/opt/llm-ops/litellm/config.yaml)
LiteLLM 将后端不同端口(8001、8002)的 vLLM 实例封装在统一的 :4000/v1 OpenAI 协议端点之后,对外提供统一鉴权与模型路由:
model_list:
- model_name: DeepSeek-R1-Distill-Qwen-7B-AWQ
litellm_params:
model: openai/DeepSeek-R1-Distill-Qwen-7B-AWQ
api_base: http://vllm-deepseek:8000/v1
api_key: "sk-local-vllm"
- model_name: Qwen3-8B-AWQ
litellm_params:
model: openai/Qwen3-8B-AWQ
api_base: http://vllm-qwen3:8000/v1
api_key: "sk-local-vllm"
litellm_settings:
drop_params: true
general_settings:
master_key: sk-llmops-master-key
4.2 Nginx HTTPS 反代与 SSE 流式优化配置 (/opt/llm-ops/nginx/nginx.conf)
4.2.1 生成自签名 SSL 证书
mkdir -p /opt/llm-ops/nginx/ssl
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /opt/llm-ops/nginx/ssl/server.key \
-out /opt/llm-ops/nginx/ssl/server.crt \
-subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=LLMOps/OU=AI/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
4.2.2 完整 /opt/llm-ops/nginx/nginx.conf
worker_processes auto;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
client_max_body_size 100M;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP 80 强制跳转 HTTPS 443
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS 443 高可用反代与 SSE 流式调优
server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 大模型 SSE 流式输出核心调优参数
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_http_version 1.1;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_connect_timeout 60s;
add_header X-Accel-Buffering no;
# LiteLLM 统一 OpenAI 兼容接口反代
location /v1/ {
proxy_pass http://litellm:4000/v1/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
}
# Open-WebUI 交互前端反代
location / {
proxy_pass http://open-webui:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
4.3 Nginx 大模型 SSE 防断连与流式优化参数作用机制详解
大模型推理接口(stream: true)采用 SSE(Server-Sent Events,text/event-stream ) 协议按 Token 实时推送数据,且在超长 Prompt 预填充(Prefill)或深度推理(Reasoning)阶段会出现较长的时间间隔。若使用 Nginx 默认配置,会出现“卡顿数秒后一次性蹦出一大段字”或“长文生成到一半报 504 Gateway Time-out”的问题。各核心参数作用机制如下:
-
proxy_buffering off; (核心防卡顿参数) :- 机制解析:Nginx 默认开启
proxy_buffering on;,会将上游(LiteLLM/vLLM)返回的响应先积攒在内存缓冲区(proxy_buffers)中,填满一个缓冲区页面(通常 4KB/8KB)后才向客户端发送。 - 优化效果:显式设为
off后,上游每产生一个 Token 的data: {...}\n\n数据帧,Nginx 立即零延迟透传刷新给客户端,实现丝滑的逐字打字机效果。
- 机制解析:Nginx 默认开启
-
proxy_cache off; (防止动态流响应被缓存) :- 机制解析:显式关闭 Nginx 对流式推理接口的代理缓存,避免不同请求或长连接流状态被错误写入磁盘缓存。
-
chunked_transfer_encoding on; (支持未知长度分块流式传输) :- 机制解析:大模型在开始流式生成第一个 Token 时,无法预知最终生成的总字节数(即无
Content-Length响应头)。开启Transfer-Encoding: chunked允许服务端以分块流的形式持续追加发送 Token 数据直至发送data: [DONE]。
- 机制解析:大模型在开始流式生成第一个 Token 时,无法预知最终生成的总字节数(即无
-
proxy_http_version 1.1; ** 与 proxy_set_header Connection ""; **(保障长连接与 HTTP/1.1 流) :- 机制解析:Nginx 反向代理默认对上游使用
HTTP/1.0并发送Connection: close,而Transfer-Encoding: chunked和 SSE 长连接依赖 HTTP/1.1 协议规范。显式指定1.1并清空Connection头(WebUI 处则配合$connection_upgrade支持 WebSocket 升级),确保上游长连接不断开。
- 机制解析:Nginx 反向代理默认对上游使用
-
proxy_read_timeout 600s; ** & proxy_send_timeout 600s; **(防止 Prefill 阶段或深度思考阶段 504 断连) :- 机制解析:Nginx 默认
proxy_read_timeout仅为60s。当用户输入 10K+ 长文档进行 Prefill,或高并发排队导致首字延迟(TTFT)超过 60 秒,或长文输出总耗时较长时,默认配置会直接掐断连接返回504 Gateway Time-out。将其调大至600s(10 分钟)彻底消除长推理中断隐患。
- 机制解析:Nginx 默认
-
add_header X-Accel-Buffering no; (穿透多层网关防缓冲) :- 机制解析:向响应头注入
X-Accel-Buffering: no,即使前端还串联了其他兼容 Nginx 协议的企业级 Ingress 或 CDN,也能通知下游代理禁用响应该流的缓冲。
- 机制解析:向响应头注入
五、Prometheus + Grafana + DCGM 全链路监控与钉钉告警
【 过于先进,暂不展示;如需了解技术细节,请联系 Jeff 】
六、项目最终成果展示
6.1 单卡 L20 双模型共存与 10 容器全栈运行
在单张 48GB 企业级显卡(NVIDIA L20)上通过显存配额调优(0.42)跑起了两个 vLLM 大模型进程(17898MiB + 11566MiB),且底层编排了完整的 10 容器生产级微服务栈(vLLM + LiteLLM + Open-WebUI + Nginx + DCGM + Prometheus + Alertmanager + DingTalk + Grafana)。
6.2 自动化预验收与 1/4/8 并发压测基准报告
全链路 6 个端点 [PASS]、X-Accel-Buffering: no 生效,以及 DeepSeek-R1-7B-AWQ(8 并发 911.13 tok/s,TTFT 17.2ms)与 Qwen3-8B-AWQ(8 并发 724.13 tok/s),量化性能优异。
6.3 Open-WebUI 双模型并存与流式输出
DeepSeek-R1-Distill-Qwen-7B-AWQ 与 Qwen3-8B-AWQ 双模型共存。
DeepSeek-R1-Distill-Qwen-7B-AWQ 与 Qwen3-8B-AWQ 两个模型回答同一道架构设计题,可直观对比两者的推理风格与输出速度。
6.4 Prometheus Targets 全绿 (UP) 与 4 条核心告警规则页
dcgm-exporter、vllm-deepseek、vllm-qwen3、prometheus 4 个 Endpoint 全部绿色 UP。

HighGPUMemoryUtilization、HighGPUTemperature、HighVLLMTimeToFirstTokenP95、VLLMServiceDown 4 条规则。
6.5 Grafana NVIDIA DCGM GPU 硬件大盘与 vLLM 吞吐/TTFT 监控曲线
NVIDIA DCGM Exporter Dashboard 展示 NVIDIA L20 的实时 GPU 温度、功率、显存占用及 SM 算力利用率曲线。
查询双模型每秒 Token 生成吞吐率。
七、日常运维与常见故障排查手册(SOP)
7.1 故障一:OOM 显存溢出或单卡多实例启动失败 (No available memory for the cache blocks)
- 典型现象:
- 容器反复重启(
Restarting (1)),docker logs报错torch.OutOfMemoryError: CUDA out of memory。 - 或者单卡启动第二个 vLLM 实例时报错:
ValueError: No available memory for the cache blocks. Try increasing gpu_memory_utilization when initializing the engine.
- 容器反复重启(
- 排查命令:
# 1. 查看当前 GPU 各进程显存占用明细 nvidia-smi # 2. 查看对应 vLLM 容器日志中的 Memory profiling 统计 docker logs --tail 80 vllm-qwen3 | grep -E "Memory profiling|model weights take|ValueError|OutOfMemory" - 根治方案:
- 单卡多实例共存必加 **
VLLM_USE_V1=0**:在 vLLMv0.8.x中,默认 V1 引擎会将其他进程占用的显存从当前实例的gpu_memory_utilization配额中扣除;在environment中设置VLLM_USE_V1=0切换回 V0 引擎即可按单进程独立配额(如各0.42)稳定共存。 - 收敛 ** **
--max-model-len ** 与 **--max-num-seqs:将超长默认上下文(如 128K)下调至业务实际需要的16384或8192,并将--max-num-seqs从 256 降至32或64,显著降低 Activation Peak Memory 和 KV Cache 预分配压力。 - 必要时开启 ** **
--enforce-eager:若在Capturing cudagraphs for decoding阶段发生 OOM,可添加--enforce-eager禁用 CUDA Graph 捕获以节省 0.5~1.5 GiB 显存。
- 单卡多实例共存必加 **
7.2 故障二:长文本生成或深度思考(Reasoning)中途 504 Gateway Time-out / 流式卡顿
- 典型现象:
- 用户请求输入万字长文或复杂数学推理题时,前端等待约 60 秒后直接断开并报错
504 Gateway Time-out。 - 流式对话不逐字输出,而是停顿数秒后一段一段跳出。
- 用户请求输入万字长文或复杂数学推理题时,前端等待约 60 秒后直接断开并报错
- 排查命令:
# 1. 检查 Nginx 错误日志是否出现 upstream timed out (110: Operation timed out) docker logs --tail 50 llmops-nginx # 2. 绕过 Nginx 直连 LiteLLM (:4000) 或 vLLM (:8001) 进行对比流式测试 curl --noproxy '*' -N http://127.0.0.1:4000/v1/chat/completions \ -H "Content-Type: application/json" -H "Authorization: Bearer sk-llmops-master-key" \ -d '{"model":"DeepSeek-R1-Distill-Qwen-7B-AWQ","messages":[{"role":"user","content":"你好"}],"stream":true}' - 根治方案:
- 检查
/opt/llm-ops/nginx/nginx.conf,确保配置了proxy_buffering off;、proxy_cache off;、proxy_http_version 1.1;、chunked_transfer_encoding on;。 - 将
proxy_read_timeout与proxy_send_timeout从默认的 60s 调大至600s,执行docker exec llmops-nginx nginx -s reload热重载生效。
- 检查
7.3 故障三:多卡张量并行(Tensor Parallelism)下 NCCL 通信失败或卡死
- 典型现象:
- 在 2 卡/4 卡/8 卡服务器上设置
--tensor-parallel-size 2/4/8后,vLLM 启动卡在Initializing distributed environment或报错NCCL error: unhandled system error / shm.h: No space left on device。
- 在 2 卡/4 卡/8 卡服务器上设置
- 排查命令:
# 1. 检查容器内 /dev/shm 共享内存大小(Docker 默认仅 64MB!) docker exec vllm-deepseek df -h /dev/shm # 2. 检查宿主机多卡拓扑与 P2P 支持状态 nvidia-smi topo -m - 根治方案:
- 扩大共享内存:在
docker-compose.yml中配置ipc: host或显式设置shm_size: "16g",防止 NCCL 在/dev/shm分配通信缓冲区时空间不足。 - 禁用故障 P2P 通道:在部分 PCIe 拓扑(非 NVLink)或特定虚拟化主板上,若 P2P 死锁,可在容器
environment中加入NCCL_P2P_DISABLE=1或在 vLLM 启动参数中加入--disable-custom-all-reduce。
- 扩大共享内存:在
7.4 故障四:模型下载或容器启动加载模型极度缓慢
- 典型现象:
- 下载模型权重速率仅几百 KB/s,耗时数小时。
- Open-WebUI 或 vLLM 容器启动时卡住数分钟无响应。
- 排查命令:
# 1. 检查当前 Shell 是否误挂了低速海外代理 env | grep -i proxy # 2. 检查磁盘 I/O 吞吐与容器日志 iostat -xz 1 3 || df -h docker logs --tail 50 open-webui - 根治方案:
- 严格执行代理分流:下载模型时必须清空代理环境变量(
http_proxy= https_proxy= all_proxy=),使用modelscope从阿里云魔搭社区直连下载(内网速度可达 200~450 MB/s)。 - 开启容器离线环境变量:Open-WebUI 默认启动时会尝试连接海外
huggingface.co 下载 Embedding 模型导致卡死,务必在docker-compose.yml 中配置HF_HUB_OFFLINE=1 与ENABLE_OLLAMA_API=false。
- 严格执行代理分流:下载模型时必须清空代理环境变量(
参考资料
[1] Gemini: https://gemini.google.com/
[2] 马永亮. 大模型应用与工程实践[Z]. 2026.
