使用 NVIDIA Dynamo 安装
本指南提供了将 vLLM Semantic Router 与 NVIDIA Dynamo 集成的分步说明。
关于 NVIDIA Dynamo
NVIDIA Dynamo 是一个分布式推理平台, 用于大语言模型服务。它通过智能路由和缓存机制优化 GPU 利用率、降低推理延迟。
核心特性
- 分离式服务:独立的 Prefill 和 Decode Worker
- KV 感知路由:将请求路由到具有相关 KV 缓存的 Worker,优化前缀缓存
- 动态扩展:Planner 组件根据工作负载处理自动扩展
- 多层 KV 缓存:GPU HBM → 系统内存 → NVMe,实现高效缓存管理
- Worker 协调:使用 etcd 和 NATS 进行分布式 Worker 注册和消息队列
- 后端无关:支持 vLLM、SGLang 和 TensorRT-LLM 后端
集成优势
集成两者的好处:
- Semantic Router 做请求级决策(模型选择、分类),Dynamo 做基础设施级优化(Worker 选择、KV 缓存重用)
- 语义缓存(Milvus)+ KV 缓存(Dynamo)双层缓存
- PII 检测和越狱防护在请求到达 Worker 之前过滤
- 分离式 prefill/decode Worker 配合 KV 感知路由
架构
本部署使用启用 KV 缓存的分离式路由器部署模式,prefill 和 decode Worker 分开运行。
┌─────────────────────────────────────────────────────────────────┐
│ CLIENT │
│ curl -X POST http://localhost:8080/v1/chat/completions │
│ -d '{"model": "MoM", "messages": [...]}' │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ENVOY GATEWAY │
│ • 路由流量,应用 ExtProc 过滤器 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ SEMANTIC ROUTER (ExtProc Filter) │
│ • 分类查询 → 选择类别(例如 "math") │
│ • 选择模型 → 重写请求 │
│ • 注入特定领域的系统提示词 │
│ • PII/越狱检测 │
└──────────── ─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ DYNAMO FRONTEND (KV-Aware Routing) │
│ • 接收带有所选模型的增强请求 │
│ • 根据 KV 缓存状态路由到最佳 Worker │
│ • 通过 etcd/NATS 协调 Worker │
└─────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ PREFILL WORKER (GPU 1) │ │ DECODE WORKER (GPU 2) │
│ prefillworker0 │──▶ decodeworker1 │
│ --worker-type prefill │ │ --worker-type decode │
└───────────────────────────┘ └───────────────────────────┘
部署模式
本指南部署启用 KV 缓存(frontend.routerMode=kv)的分离式路由器部署模式。KV 感知路由可跨请求重用已计算的注意力张量。
基于 NVIDIA Dynamo 部署模式,Helm chart 支持两种部署模式:
聚合模式(默认)
Worker 同时处理 prefill 和 decode 阶段。设置更简单,需要更少的 GPU。
# 未指定 workerType = 默认为 "both"
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[1].model.path=Qwen/Qwen2-0.5B-Instruct
- Worker 在 ETCD 中注册为
backend组件 - 没有
--is-prefill-worker标志 - 每个 Worker 可以处理完整的推理请求
分离模式(高性能)
独立的 prefill 和 decode Worker 分开处理。
# 显式 workerType = 分离模式
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[0].workerType=prefill \
--set workers[1].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[1].workerType=decode
| Worker | 标志 | ETCD 组件 | 角色 |
|---|---|---|---|
| Prefill | --is-prefill-worker | prefill | 处理输入 Token,生成 KV 缓存 |
| Decode | (无特殊标志) | backend | 生成输出 Token,仅接收 decode 请求 |
在分离模式下,只有 prefill Worker 使用 --is-prefill-worker 标志。Decode Worker 使用默认的 vLLM 行为(无特殊标志)。KV 感知前端将 prefill 请求路由到 prefill Worker,将 decode 请求路由到 backend Worker。
前置条件
GPU 要求
此部署需要至少 3 个 GPU 的机器:
| 组件 | GPU | 描述 |
|---|---|---|
| Frontend | GPU 0 | 带 KV 感知路由的 Dynamo Frontend(--router-mode kv) |
| Prefill Worker | GPU 1 | 处理推理的 prefill 阶段(--worker-type prefill) |
| Decode Worker | GPU 2 | 处理推理的 decode 阶段(--worker-type decode) |
必需工具
开始之前,确保已安装以下工具:
NVIDIA 运行时配置(一次性设置)
将 Docker 配置为默认使用 NVIDIA 运行时:
# 将 NVIDIA 运行时配置为默认
sudo nvidia-ctk runtime configure --runtime=docker --set-as-default
# 重启 Docker
sudo systemctl restart docker
# 验证配置
docker info | grep -i "default runtime"
# 预期输出: Default Runtime: nvidia
步骤 1:创建支持 GPU 的 Kind 集群
创建支持 GPU 的本地 Kubernetes 集群。选择以下选项之一:
选项 1:快速设置(外部文档)
要快速设置,请遵循官方 Kind GPU 文档:
kind create cluster --name semantic-router-dynamo
# 验证集群就绪
kubectl wait --for=condition=Ready nodes --all --timeout=300s
有关 GPU 支持,请参阅 Kind GPU 文档 了解配置额外挂载和部署 NVIDIA device plugin 的详细信息。
选项 2:完整 GPU 设置(E2E 流程)
这是我们 E2E 测试中使用的流程。它包含在 Kind 中设置 GPU 支持所需的所有步骤。
2.1 使用 GPU 配置创建 Kind 集群
创建支持 GPU 挂载的 Kind 配置文件:
# 创建 GPU 支持的 Kind 配置
cat > kind-gpu-config.yaml << 'EOF'
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: semantic-router-dynamo
nodes:
- role: control-plane
extraMounts:
- hostPath: /mnt
containerPath: /mnt
- role: worker
extraMounts:
- hostPath: /mnt
containerPath: /mnt
- hostPath: /dev/null
containerPath: /var/run/nvidia-container-devices/all
EOF
# 使用 GPU 配置创建集群
kind create cluster --name semantic-router-dynamo --config kind-gpu-config.yaml --wait 5m
# 验证集群就绪
kubectl wait --for=condition=Ready nodes --all --timeout=300s
2.2 在 Kind Worker 中设置 NVIDIA 库
将 NVIDIA 库从主机复制到 Kind Worker 节点:
# 设置 Worker 名称
WORKER_NAME="semantic-router-dynamo-worker"
# 检测 NVIDIA 驱动版本
DRIVER_VERSION=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader | head -1)
echo "检测到 NVIDIA 驱动版本: $DRIVER_VERSION"
# 验证 Kind Worker 中存在 GPU 设备
docker exec $WORKER_NAME ls /dev/nvidia0
echo "✅ 在 Kind Worker 中找到 GPU 设备"
# 为 NVIDIA 库创建目录
docker exec $WORKER_NAME mkdir -p /nvidia-driver-libs
# 复制 nvidia-smi 二进制文件
tar -cf - -C /usr/bin nvidia-smi | docker exec -i $WORKER_NAME tar -xf - -C /nvidia-driver-libs/
# 从主机复制 NVIDIA 库
tar -cf - -C /usr/lib64 libnvidia-ml.so.$DRIVER_VERSION libcuda.so.$DRIVER_VERSION | \
docker exec -i $WORKER_NAME tar -xf - -C /nvidia-driver-libs/
# 创建符号链接
docker exec $WORKER_NAME bash -c "cd /nvidia-driver-libs && \
ln -sf libnvidia-ml.so.$DRIVER_VERSION libnvidia-ml.so.1 && \
ln -sf libcuda.so.$DRIVER_VERSION libcuda.so.1 && \
chmod +x nvidia-smi"
# 在 Kind Worker 内验证 nvidia-smi
docker exec $WORKER_NAME bash -c "LD_LIBRARY_PATH=/nvidia-driver-libs /nvidia-driver-libs/nvidia-smi"
echo "✅ 在 Kind Worker 中验证 nvidia-smi 成功"
2.3 部署 NVIDIA Device Plugin
部署 NVIDIA device plugin 以使 GPU 在 Kubernetes 中可分配:
# 创建 device plugin 清单
cat > nvidia-device-plugin.yaml << 'EOF'
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: nvidia-device-plugin-ds
template:
metadata:
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- image: nvcr.io/nvidia/k8s-device-plugin:v0.14.1
name: nvidia-device-plugin-ctr
env:
- name: LD_LIBRARY_PATH
value: "/nvidia-driver-libs"
securityContext:
privileged: true
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
- name: dev
mountPath: /dev
- name: nvidia-driver-libs
mountPath: /nvidia-driver-libs
readOnly: true
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
- name: dev
hostPath:
path: /dev
- name: nvidia-driver-libs
hostPath:
path: /nvidia-driver-libs
EOF
# 应用 device plugin
kubectl apply -f nvidia-device-plugin.yaml
# 等待 device plugin 就绪
sleep 20
# 验证 GPU 可分配
kubectl get nodes -o custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\\.com/gpu
echo "✅ GPU 设置完成"
Semantic Router 项目包含自动化的 E2E 测试,可自动处理所有这些 GPU 设置。你可以运行:
make e2e-test E2E_PROFILE=dynamo E2E_VERBOSE=true
这将创建支持 GPU 的 Kind 集群,部署所有组件,并运行测试套件。
步骤 2:安装 Dynamo 平台
部署 Dynamo 平台组件(etcd、NATS、Dynamo Operator):
# 添加 Dynamo Helm 仓库
helm repo add dynamo https://nvidia.github.io/dynamo
helm repo update
# 安装 Dynamo CRDs
helm install dynamo-crds dynamo/dynamo-crds \
--namespace dynamo-system \
--create-namespace
# 安装 Dynamo 平台(etcd、NATS、Operator)
helm install dynamo-platform dynamo/dynamo-platform \
--namespace dynamo-system \
--wait
# 等待平台组件就绪
kubectl wait --for=condition=Available deployment -l app.kubernetes.io/instance=dynamo-platform -n dynamo-system --timeout=300s
步骤 3:安装 Envoy Gateway
部署启用 ExtensionAPIs 的 Envoy Gateway 以支持 Semantic Router 集成:
# 使用自定义 values 安装 Envoy Gateway
helm install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
--version v1.3.0 \
--namespace envoy-gateway-system \
--create-namespace \
-f https://raw.githubusercontent.com/vllm-project/semantic-router/refs/heads/main/deploy/kubernetes/dynamo/dynamo-resources/envoy-gateway-values.yaml
# 等待 Envoy Gateway 就绪
kubectl wait --for=condition=Available deployment/envoy-gateway -n envoy-gateway-system --timeout=300s
重要:values 文件启用了 extensionApis.enableEnvoyPatchPolicy: true,这是 Semantic Router ExtProc 集成所必需的。
步骤 4:部署 vLLM Semantic Router
使用 Dynamo 特定配置部署 Semantic Router:
# 从 GHCR OCI registry 安装 Semantic Router
helm install semantic-router oci://ghcr.io/vllm-project/charts/semantic-router \
--version v0.0.0-latest \
--namespace vllm-semantic-router-system \
--create-namespace \
-f https://raw.githubusercontent.com/vllm-project/semantic-router/refs/heads/main/deploy/kubernetes/dynamo/semantic-router-values/values.yaml
# 等待部署就绪
kubectl wait --for=condition=Available deployment/semantic-router -n vllm-semantic-router-system --timeout=600s
# 验证部署状态
kubectl get pods -n vllm-semantic-router-system
注意:values 文件配置 Semantic Router 将请求路由到由 Dynamo Worker 服务的 TinyLlama 模型。
步骤 5:部署 RBAC 资源
应用 RBAC 权限以使 Semantic Router 能够访问 Dynamo CRDs:
kubectl apply -f https://raw.githubusercontent.com/vllm-project/semantic-router/refs/heads/main/deploy/kubernetes/dynamo/dynamo-resources/rbac.yaml
步骤 6:部署 Dynamo vLLM Worker
使用 Helm chart 部署 Dynamo Worker。这提供了灵活的基于 CLI 的配置,无需编辑 YAML 文件。
选项 A:使用 Helm Chart(推荐)
# 克隆仓库(如果尚未克隆)
git clone https://github.com/vllm-project/semantic-router.git
cd semantic-router
# 使用默认 TinyLlama 模型进行基本安装
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system
# 等待 Worker 就绪
kubectl wait --for=condition=Available deployment -l app.kubernetes.io/instance=dynamo-vllm -n dynamo-system --timeout=600s
选项 B:通过 CLI 自定义模型
无需编辑任何文件即可使用自定义模型部署:
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[1].model.path=Qwen/Qwen2-0.5B-Instruct
选项 C:显式 Prefill/Decode 配置
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[0].workerType=prefill \
--set workers[1].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[1].workerType=decode
选项 D:门控模型(Llama、Mistral)
对于需要 HuggingFace 身份验证的模型:
# 创建包含 HuggingFace token 的 secret
kubectl create secret generic hf-secret \
--from-literal=HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxx \
-n dynamo-system
# 使用 secret 引用安装
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set huggingface.existingSecret=hf-secret \
--set workers[0].model.path=meta-llama/Llama-2-7b-chat-hf \
--set workers[1].model.path=meta-llama/Llama-2-7b-chat-hf
选项 E:自定义 GPU 设备分配
指定每个 Worker 应使用的 GPU:
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set frontend.gpuDevice=0 \
--set workers[0].gpuDevice=1 \
--set workers[0].workerType=prefill \
--set workers[1].gpuDevice=2 \
--set workers[1].workerType=decode
如果不指定 gpuDevice,Helm chart 使用智能默认值:
- Frontend:GPU 0
- Worker 0:GPU 1(index + 1)
- Worker 1:GPU 2(index + 1)
- Worker N:GPU N+1
这确保 GPU 0 保留给 frontend,Worker 自动分配到后续 GPU。只有当你有特定的 GPU 布局要求时才需要覆盖这些设置。
选项 F:组合 Worker 模式(非分离式)
使用单个 Worker 同时处理 prefill 和 decode(更简单,需要更少 GPU):
# 单个同时处理 prefill+decode 的 Worker(总共只需要 2 个 GPU)
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[0].workerType=both \
--set workers[0].gpuDevice=1
选项 G:模型调优参数
配置模型特定参数:
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[0].model.maxModelLen=4096 \
--set workers[0].model.gpuMemoryUtilization=0.85 \
--set workers[0].model.enforceEager=true \
--set workers[1].model.path=Qwen/Qwen2-0.5B-Instruct \
--set workers[1].model.maxModelLen=4096 \
--set workers[1].model.gpuMemoryUtilization=0.85 \
--set workers[1].model.enforceEager=true
选项 H:使用节点选择器的多节点部署
将 Worker 固定到特定的 GPU 节点:
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=meta-llama/Llama-2-7b-chat-hf \
--set workers[0].nodeSelector."kubernetes\.io/hostname"=gpu-node-1 \
--set workers[1].model.path=meta-llama/Llama-2-7b-chat-hf \
--set workers[1].nodeSelector."kubernetes\.io/hostname"=gpu-node-2
选项 I:自定义资源(CPU/内存)
覆盖 CPU 和内存分配:
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set workers[0].model.path=meta-llama/Llama-2-7b-chat-hf \
--set workers[0].resources.requests.cpu=4 \
--set workers[0].resources.requests.memory=32Gi \
--set workers[0].resources.limits.cpu=8 \
--set workers[0].resources.limits.memory=64Gi \
--set workers[1].model.path=meta-llama/Llama-2-7b-chat-hf \
--set workers[1].resources.requests.cpu=4 \
--set workers[1].resources.requests.memory=32Gi \
--set workers[1].resources.limits.cpu=8 \
--set workers[1].resources.limits.memory=64Gi
选项 J:使用 Values 文件
对于复杂配置,使用 values 文件:
# 使用多模型示例
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
-f ./deploy/kubernetes/dynamo/helm-chart/examples/values-multi-model.yaml
# 或多节点示例
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
-f ./deploy/kubernetes/dynamo/helm-chart/examples/values-multi-node.yaml
选项 K:Frontend 路由模式
更改 frontend 路由算法:
# KV 感知路由(默认,推荐)
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set frontend.routerMode=kv
# 轮询路由
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set frontend.routerMode=round-robin
# 随机路由
helm install dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--set frontend.routerMode=random
升级现有部署
无需重新安装即可更新模型或配置:
# 更改模型
helm upgrade dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--reuse-values \
--set workers[0].model.path=new-model-name \
--set workers[1].model.path=new-model-name
# 扩展副本
helm upgrade dynamo-vllm ./deploy/kubernetes/dynamo/helm-chart \
--namespace dynamo-system \
--reuse-values \
--set workers[0].replicas=2 \
--set workers[1].replicas=2
验证 Worker 部署
kubectl get pods -n dynamo-system
# 预期输出:
# dynamo-vllm-frontend-xxx 1/1 Running
# dynamo-vllm-prefillworker0-xxx 1/1 Running
# dynamo-vllm-decodeworker1-xxx 1/1 Running
Helm chart 创建:
- Frontend:带 KV 感知路由的 HTTP API 服务器(GPU 0)
- prefillworker0:用于提示处理的 Prefill Worker(GPU 1)
- decodeworker1:用于 Token 生成的 Decode Worker(GPU 2)
步骤 7:创建 Gateway API 资源
部署 Gateway API 资源以连接所有组件:
kubectl apply -f https://raw.githubusercontent.com/vllm-project/semantic-router/refs/heads/main/deploy/kubernetes/dynamo/dynamo-resources/gwapi-resources.yaml
# 验证 EnvoyPatchPolicy 被接受
kubectl get envoypatchpolicy -n default
重要:EnvoyPatchPolicy 状态必须显示 Accepted: True。如果显示 Accepted: False,请验证 Envoy Gateway 是否使用正确的 values 文件安装。