前言
随着大模型在企业场景的深入应用,越来越多的团队开始考虑私有化部署方案。对于100-499人规模的企业团队,如何在保障数据安全的前提下,高效、稳定地部署AI大模型服务于代码生成和知识问答场景,是一个典型的技术挑战。
一、整体架构蓝图
我们采用“Kubernetes集群 + vLLM推理引擎 + Qwen模型 + Dify应用平台”的黄金组合

二、环境准备
2.1 硬件要求
根据团队规模(100-499人),建议配置:
重要:多GPU部署时,必须确保GPU之间通过NVLink互联,否则PCIe会成为性能瓶颈
2.2 软件环境
操作系统:Ubuntu 22.04 LTS
Kubernetes版本:1.28+
容器运行时:Containerd
NVIDIA驱动版本:525+
Helm版本:3.x
2.3 节点标签配置
#k8s加入节点请查看>k8s搭建<
为GPU节点打上标签,便于调度器识别:
# 查看已有节点
kubectl get nodes
# 为GPU节点打标签(以阿里云ACK为例)
kubectl label nodes \
-l aliyun.accelerator/xpu_type=nvidia \
gpu=on \
--overwrite
# 非云环境
kubectl label node <gpu-node-name> gpu=on --overwrite
# 标记GPU型号(用于精确调度)
kubectl label nodes <node-name> accelerator=a100-80g
三、GPU调度层部署
3.1 方案一:NVIDIA Device Plugin(标准GPU独占)
适用于需要独占GPU卡的生产环境:
# 添加NVIDIA Helm仓库
helm repo add nvidia https://nvidia.github.io/k8s-device-plugin
helm repo update
# 安装Device Plugin
helm install nvidia-device-plugin \
nvidia/k8s-device-plugin \
--namespace kube-system \
--set devicePlugin.enabled=true
验证安装:
kubectl get pods -n kube-system | grep nvidia-device-plugin
kubectl describe node <gpu-node> | grep nvidia.com/gpu
3.2 方案二:HAMi(GPU虚拟化/分片)
适用于需要GPU共享、提高利用率的场景,可将一张物理GPU切分为多个虚拟GPU份额:
# 添加HAMi Helm仓库
helm repo add hami https://Project-HAMi.github.io/HAMi
helm repo update hami
# 安装HAMi(需先打gpu=on标签)
helm install hami hami/hami \
--namespace kube-system \
--set device.nvidia.driver.enabled=false \
--set global.managedNodeSelectorEnable=true \
--set global.managedNodeSelector.gpu=on \
--set devicePlugin.deviceSplitCount=10
验证安装:
kubectl get pods -n kube-system -l app.kubernetes.io/instance=hami
kubectl get nodes -o custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\\.com/gpu
四、模型数据准备
4.1 下载Qwen模型
以Qwen1.5-4B-Chat为例(生产环境建议使用Qwen2.5-14B/32B):
# 安装Git和Git LFS
yum install git git-lfs -y # CentOS/RHEL
# 或 apt install git git-lfs -y # Ubuntu
# 从ModelScope克隆模型(国内速度快)
GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/qwen/Qwen1.5-4B-Chat.git
# 进入目录,拉取大文件
cd Qwen1.5-4B-Chat
git lfs pull
4.2 上传到对象存储(推荐)
对于生产环境,建议将模型存储在OSS或NAS中,通过PV/PVC挂载:
# 安装ossutil(阿里云示例)
wget https://gosspublic.alicdn.com/ossutil/1.7.13/ossutil64
chmod +x ossutil64
./ossutil64 config
# 创建Bucket目录并上传
./ossutil64 mkdir oss://<your-bucket>/models/Qwen1.5-4B-Chat
./ossutil64 cp -r ./Qwen1.5-4B-Chat oss://<your-bucket>/models/Qwen1.5-4B-Chat
4.3 创建K8s存储资源(PV/PVC)
创建PV配置文件 pvc-oss.yaml:
apiVersion: v1
kind: PersistentVolume
metadata:
name: llm-model-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
csi:
driver: ossplugin.csi.alibabacloud.com
volumeHandle: llm-model-pv
volumeAttributes:
bucket: <your-bucket>
path: /models/Qwen1.5-4B-Chat
otherOpts: "-o umask=022 -o max_stat_cache_size=0 -o allow_other"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: llm-model-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
volumeName: llm-model-pv
创建存储资源:
kubectl apply -f pvc-oss.yaml
kubectl get pvc | grep llm-model
五、部署vLLM推理服务
5.1 使用Arena部署(推荐)
Arena是阿里云开源的K8s AI任务管理工具,可简化推理服务部署:
安装Arena客户端:
# 下载安装Arena
curl -LO https://aliacs-k8s-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/arena/arena-installer-0.9.15-linux-amd64.tar.gz
tar -xzf arena-installer-0.9.15-linux-amd64.tar.gz
cd arena-installer
./install.sh --only-binary
部署推理服务(单卡A10,生产推荐):
arena serve custom \
--name=vllm-qwen \
--version=v1 \
--gpus=1 \
--replicas=1 \
--restful-port=8000 \
--readiness-probe-action="tcpSocket" \
--readiness-probe-action-option="port: 8000" \
--readiness-probe-option="initialDelaySeconds: 60" \
--readiness-probe-option="periodSeconds: 30" \
--image=vllm/vllm-openai:v0.8.5 \
--data=llm-model-pvc:/model/Qwen1.5-4B-Chat \
"python3 -m vllm.entrypoints.openai.api_server \
--trust-remote-code \
--model /model/Qwen1.5-4B-Chat/ \
--gpu-memory-utilization 0.95 \
--max-model-len 16384"
部署推理服务(单卡T4,测试环境):
arena serve custom \
--name=vllm-qwen \
--version=v1 \
--gpus=1 \
--replicas=1 \
--restful-port=8000 \
--image=vllm/vllm-openai:v0.8.5 \
--data=llm-model-pvc:/model/Qwen1.5-4B-Chat \
"python3 -m vllm.entrypoints.openai.api_server \
--trust-remote-code \
--model /model/Qwen1.5-4B-Chat/ \
--gpu-memory-utilization 0.95 \
--max-model-len 8192 \
--dtype half"
关键参数说明:
5.2 使用原生K8s YAML部署
若不想使用Arena,可直接使用K8s原生资源:
创建 vllm-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-qwen
spec:
replicas: 1
strategy:
type: Recreate # 多GPU时必须用Recreate,否则滚动更新会死锁
selector:
matchLabels:
app: vllm-qwen
template:
metadata:
labels:
app: vllm-qwen
spec:
runtimeClassName: nvidia
containers:
- name: vllm
image: vllm/vllm-openai:v0.8.5
args:
- "python3 -m vllm.entrypoints.openai.api_server"
- "--model=/model/Qwen1.5-4B-Chat"
- "--trust-remote-code"
- "--gpu-memory-utilization=0.95"
- "--max-model-len=16384"
- "--tensor-parallel-size=2" # 多卡并行时启用
resources:
limits:
nvidia.com/gpu: "2" # 申请2张GPU
volumeMounts:
- name: model-storage
mountPath: /model
ports:
- containerPort: 8000
volumes:
- name: model-storage
persistentVolumeClaim:
claimName: llm-model-pvc
---
apiVersion: v1
kind: Service
metadata:
name: vllm-qwen-service
spec:
selector:
app: vllm-qwen
ports:
- port: 8000
targetPort: 8000
type: ClusterIP
部署:
kubectl apply -f vllm-deployment.yaml
kubectl get pods -l app=vllm-qwen
kubectl get svc vllm-qwen-service
5.3 多GPU张量并行配置
对于需要多卡并行的场景(如Qwen2.5-14B需要4张V100 16GB),关键配置如下:
spec:
strategy:
type: Recreate # 必须
containers:
- args:
- "--tensor-parallel-size=4" # 张量并行度等于GPU数量
resources:
limits:
nvidia.com/gpu: "4"
nodeSelector:
kubernetes.io/hostname: gpu-node-02 # 固定到有4张NVLink互联GPU的节点
为什么必须用Recreate? 滚动更新时,新Pod无法获得旧Pod占用的GPU,导致调度死锁。Recreate策略会先删除旧Pod再创建新Pod。
5.4 验证服务
# 查看服务状态
arena serve get vllm-qwen
# 端口转发(仅用于测试,生产环境用Ingress)
kubectl port-forward svc/vllm-qwen-v1 8000:8000
# 发送测试请求(集群内部)
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "/model/Qwen1.5-4B-Chat/",
"messages": [{"role": "user", "content": "写一个Python快速排序"}],
"max_tokens": 500,
"temperature": 0.7
}'
预期输出包含模型生成的代码,表明服务部署成功。
六、部署Dify应用平台
6.1 安装Dify
# 克隆Dify仓库
git clone https://github.com/langgenius/dify.git
cd dify/docker
# 复制环境变量
cp .env.example .env
# 启动Dify
docker compose up -d
6.2 在K8s中部署Dify(生产推荐可选)
创建 dify-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify
spec:
replicas: 2
selector:
matchLabels:
app: dify
template:
metadata:
labels:
app: dify
spec:
containers:
- name: dify-api
image: langgenius/dify-api:latest
ports:
- containerPort: 5001
env:
- name: MODE
value: api
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: dify-secret
key: secret-key
# 添加其他环境变量...
---
apiVersion: v1
kind: Service
metadata:
name: dify-service
spec:
selector:
app: dify
ports:
- port: 80
targetPort: 5001
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dify-ingress
spec:
rules:
- host: ai.yourcompany.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dify-service
port:
number: 80
部署:
kubectl apply -f dify-deployment.yaml
kubectl get ingress
6.3 配置Dify连接vLLM
访问
http://ai.yourcompany.com登录Dify进入「设置」→「模型供应商」
选择「OpenAI-API-compatible」
填写配置:
模型名称:
/model/Qwen1.5-4B-Chat/API Endpoint URL:
http://vllm-qwen-service.default.svc.cluster.local:8000/v1API Key:随意填写(内网无鉴权时用占位符)
七、用户访问与对外暴露
7.1 通过Ingress对外暴露
创建 vllm-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vllm-ingress
spec:
ingressClassName: nginx
rules:
- host: model-api.yourcompany.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: vllm-qwen-service
port:
number: 8000
7.2 使用LoadBalancer(云环境)
apiVersion: v1
kind: Service
metadata:
name: vllm-qwen-public
spec:
type: LoadBalancer
selector:
app: vllm-qwen
ports:
- port: 80
targetPort: 8000
八、GPU算力分配策略
8.1 三种分配模式对比(根据实际选择)
8.2 HAMi GPU分片示例
使用HAMi时,可以为Pod申请部分GPU显存和算力:
spec:
containers:
- resources:
limits:
nvidia.com/gpu: 1 # 1个虚拟GPU
nvidia.com/gpumem: 22000 # 22GB显存
nvidia.com/gpucores: 100 # 100%算力
查看GPU可分配资源:
kubectl get nodes -o custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\\.com/gpu
8.3 时间切片(Time-Slicing)示例
时间切片是一种GPU共享调度策略,它允许多个Pod分时共享同一张物理GPU。与MIG的硬隔离不同,时间切片是“软隔离”,多个任务轮流使用GPU计算单元,但显存是共享的(需要注意隔离性),时间切片功能由NVIDIA GPU Operator提供,它包含了Device Plugin和配置时间切片所需的组件:
部署NVIDIA GPU Operator
# 添加NVIDIA Helm仓库
helm repo add nvidia https://nvidia.github.io/gpu-operator
helm repo update
# 安装GPU Operator(默认会启用Device Plugin)
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace \
--set devicePlugin.enabled=true
开启时间切片功能
时间切片通过配置nvidia.com/vgpu资源来实现。注意:需要在安装GPU Operator时进行配置,否则默认不开启:
helm install gpu-operator nvidia/gpu-operator \
--namespace gpu-operator \
--create-namespace \
--set devicePlugin.enabled=true \
--set migStrategy=none \
--set devicePlugin.config.name=time-slicing-config
若已安装,通过values.yaml方式修改配置:
# values.yaml
devicePlugin:
enabled: true
config:
name: time-slicing-config
extraConfig: |
version: v1
flags:
migStrategy: none
sharing:
timeSlicing:
renameByDefault: false
resources:
- name: nvidia.com/gpu
replicas: 4 # 每张物理GPU虚拟成4份
应用配置:
helm upgrade gpu-operator nvidia/gpu-operator -f values.yaml -n gpu-operator
使用时间切片的Pod示例
开启时间切片后,多个Pod可以通过申请nvidia.com/gpu资源来共享同一张物理GPU:
apiVersion: v1
kind: Pod
metadata:
name: vllm-qwen-time-slicing
labels:
app: vllm-qwen-time-slicing
spec:
runtimeClassName: nvidia
containers:
- name: vllm
image: vllm/vllm-openai:v0.8.5
args:
- "python3 -m vllm.entrypoints.openai.api_server"
- "--model=/model/Qwen1.5-4B-Chat"
- "--trust-remote-code"
- "--gpu-memory-utilization=0.8"
- "--max-model-len=4096"
resources:
limits:
nvidia.com/gpu: 1 # 申请1个时间切片(虚拟GPU),而非独占物理卡
volumeMounts:
- name: model-storage
mountPath: /model
volumes:
- name: model-storage
persistentVolumeClaim:
claimName: llm-model-pvc
验证时间切片是否生效
# 查看节点GPU分配状态,会显示虚拟GPU数量
kubectl describe node <gpu-node> | grep nvidia.com/gpu
# 查看Pod中可见的GPU
kubectl exec -it <pod-name> -- nvidia-smi
九、验证与测试
9.1 完整测试流程
# 1. 检查服务状态
kubectl get pods -l app=vllm-qwen
kubectl logs -f <pod-name>
# 2. 内部调用测试(集群内)
kubectl run test-pod --rm -it --image=curlimages/curl -- sh
curl http://vllm-qwen-service:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "/model/Qwen1.5-4B-Chat/", "messages": [{"role": "user", "content": "你好"}], "max_tokens": 20}'
# 3. 外部调用测试
curl https://model-api.yourcompany.com/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "/model/Qwen1.5-4B-Chat/", "messages": [{"role": "user", "content": "解释什么是RAG"}], "max_tokens": 200}'
9.2 通过Dify创建第一个应用
登录Dify,创建「空白应用」
选择「聊天助手」
在模型选择中选择已配置的vLLM-Qwen模型
添加知识库(上传企业内部文档)
发布并测试
十、常用运维命令速查
# 查看推理服务状态
arena serve get vllm-qwen
# 查看Pod日志
kubectl logs -f deployment/vllm-qwen-v1-custom-serving
# 扩容
kubectl scale deployment vllm-qwen-v1-custom-serving --replicas=3
# 查看GPU使用情况
kubectl exec -it <pod-name> -- nvidia-smi
# 删除服务
arena serve delete vllm-qwen
# 查看节点GPU资源
kubectl describe node <gpu-node> | grep -A5 "Allocated resources"
十一、常见问题排查
Q1: Pod状态为Pending
kubectl describe pod <pod-name>
常见原因:
GPU资源不足:检查节点是否有可用GPU
PVC未绑定:检查
kubectl get pvc节点标签不匹配:检查nodeSelector
Q2: GPU OOM(显存溢出)
调整以下参数:
降低
--max-model-len降低
--gpu-memory-utilization(如0.85)使用量化模型或
--dtype half
Q3: 多GPU滚动更新死锁
确保Deployment使用strategy.type: Recreate,而非默认的RollingUpdate。
核心要点:
Kubernetes作为底座:提供弹性、高可用
vLLM作为推理引擎:高性能、OpenAI-API兼容
Qwen作为模型基座:中文能力强、开源生态好
Dify作为应用平台:低代码、快速构建业务应用