本文演示如何使用云容器引擎控制臺,使用vLLM提交部署DeepSeek-R1 并提供UI交互界面。
背景
本文使用4臺機器,每臺機器8張L40S(48G顯存),共32x48GB GPUs
vLLM 是用于運行大語言模型(LLM)推理和服務的工具,針對推理做了很多優化,提高了模型的運行效率和性能,使得在資源有限的情況下也能高效運行大語言模型,提供了兼容 OpenAI 的 API,支持多機多卡分布式部署。
Open WebUI是一個專為本地大語言模型(LLMs)設計的Web界面,它支持多種大語言模型運行工具,例如Ollama、vLLM等。
準備工作
-
已開通包含GPU/NPU節點的Kubernetes集群。
-
已安裝智算套件。
添加GPU節點(若集群已有GPU資源,請忽略)
-
點擊云容器引擎控制臺左側【節點】->【節點池】,點擊【創建節點池】
在規格中可選擇【x86計算】或【彈性裸金屬服務器】中的【GPU計算加速型】或【GPU型】,節點池創建成功后,進入節點池列表,擴容節點至期望的節點數量。
網絡準備
由于需要聯網拉取容器鏡像和獲取模型文件,故需要集群所在節點能夠訪問外網,具體配置可參考VPC虛擬私有網絡的“管理SNAT規則“
存儲準備
由于模型文件通常較大,建議將模型文件提保存在共享存儲中,供集群中的節點mount使用,本文以使用ZOS為例演示
首先需要創建能夠訪問ZOS的憑證,具體可參考“使用ZOS動態存儲卷”
kubectl create secret generic oss-secret-test --from-literal=AK='<ZOS accesskey>' --from-literal=SK='<ZOS secreykey>'
接下來創建用于保存模型文件的StrongClass和PVC
通過kube APIServer
創建StorageClass,其中需要在參數中指定
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: models-vllm
parameters:
azpolicy: single-az
csi.storage.k8s.io/node-publish-secret-name: oss-secret-test
csi.storage.k8s.io/node-publish-secret-namespace: default
type: STANDARD
provisioner: zos.csi.cstor.com
reclaimPolicy: Delete
volumeBindingMode: Immediate
創建PVC,關聯StorageClass,其中訪問模式修改成多機讀寫ReadWriteMany,storage根據模型大小適當修改
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: models-vllm
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1500Gi
storageClassName: models-vllm
獲取模型
本文通過使用git lfs拉取魔樂社區模型(同hugging face),使用vllm運行
啟動Job用于拉取模型文件,并保存在ZOS
在控制臺中啟動如下任務,注意選擇期望的命名空間
注意:修改對應的鏡像倉庫前綴為對應資源池,可在容器鏡像控制臺查看,如杭州7,則修改{image_repo}為registry-vpc-crs-hangzhou7.cnsp-internal.daliqc.cn
apiVersion: batch/v1
kind: Job
metadata:
name: download-model
labels:
app: download-model
spec:
template:
metadata:
name: download-model
labels:
app: download-model
spec:
containers:
- name: download
image: {image_repo}/icce/git:2.48.1
command:
- bash
- -c
- |
cd /data; git clone ${模型倉庫}
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: models-vllm
restartPolicy: OnFailure
等待任務執行完畢(可通過日志查看文件是否成功)
任務執行完畢后,模型文件就保存在ZOS的PV中的,我們會在后面的流程中使用到
運行模型服務
通過vllm運行分布式任務,以1master,3worker為例,每個Pod有8張卡
通過Kube APIServer提交以下yaml文件
注意:修改對應的鏡像倉庫前綴為對應資源池,可在容器鏡像控制臺查看,如杭州7,則修改{image_repo}為registry-vpc-crs-hangzhou7.cnsp-internal.daliqc.cn
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-master
spec:
replicas: 1 # master只需要一個副本
selector:
matchLabels:
app: vllm-master
template:
metadata:
labels:
app: vllm-master
spec:
containers:
- name: vllm-master
image: {image_repo}/icce/vllm-openai:v0.7.3
command: ["/bin/bash", "-c", "ray start --block --head --port=6379 & vllm serve /data/DeepSeek-R1-origin --host 0.0.0.0 --port 8000 --trust-remote-code --enable-chunked-prefill --tensor-parallel-size 8 --pipeline-parallel-size 4 --gpu-memory-utilization 0.90 --enforce-eager "]
resources:
requests:
nvidia.com/gpu: "8"
rdma/rdma_shared_device_a: "1"
limits:
nvidia.com/gpu: "8"
rdma/rdma_shared_device_a: "1"
env:
- name: VLLM_HOST_IP
valueFrom:
fieldRef:
fieldPath: status.podIP # 從環境變量獲取 Pod IP
- name: NCCL_SHM_DISABLE
value: "1"
volumeMounts:
- mountPath: /data
name: vllm-models
- name: shm
mountPath: /dev/shm
volumes:
- name: vllm-models
persistentVolumeClaim:
claimName: models-vllm
- name: shm
emptyDir:
medium: Memory
sizeLimit: 500Gi
---
apiVersion: v1
kind: Service
metadata:
name: vllm-master-svc
labels:
app: vllm-master
spec:
clusterIP: None # Headless service
selector:
app: vllm-master
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-worker
spec:
replicas: 3 # worker節點數量
selector:
matchLabels:
app: vllm-worker
template:
metadata:
labels:
app: vllm-worker
spec:
containers:
- name: vllm-worker
image: {image_repo}/icce/vllm-openai:v0.7.3
command: ["/bin/bash", "-c", "ray start --block --address=vllm-master-svc:6379"]
resources:
requests:
nvidia.com/gpu: "8"
rdma/rdma_shared_device_a: "1"
limits:
nvidia.com/gpu: "8"
rdma/rdma_shared_device_a: "1"
env:
- name: VLLM_HOST_IP
valueFrom:
fieldRef:
fieldPath: status.podIP # 從環境變量獲取 Pod IP
- name: NCCL_SHM_DISABLE
value: "1"
volumeMounts:
- mountPath: /data
name: vllm-models
- name: shm
mountPath: /dev/shm
volumes:
- name: vllm-models
persistentVolumeClaim:
claimName: models-vllm
- name: shm
emptyDir:
medium: Memory
sizeLimit: 500Gi
其中需要注意以下幾點:
-
指定使用之前download模型的PVC,并mount到vllm serve后參數指定的啟動目錄(/data)
-
master數量只有一個,worker節點數量根據模型實際大小和GPU顯存大小、數量適當調整
-
master啟動參數:確保tensor-parallel-size × pipeline-parallel-size =(master+worker)× 單pod GPU申請數量,通常 tensor-parallel-size 的值為單pod申請卡數 pipeline-parallel-size 為pod數量(即master+worker),其余參數若遇到錯誤可自行調整
部署OpenWebUI服務
首先創建用于保存OpenWebUI數據的PVC
創建OpenWebUI
注意:由于從官方拉取鏡像可能存在失敗的情況,可替換鏡像為天翼云的容器鏡像:registry-vpc-crs-hangzhou7.cnsp-internal.daliqc.cn:443/icce/open-webui:main,其中hangzhou7請根據實際使用的資源池進行替換
apiVersion: apps/v1
kind: Deployment
metadata:
name: open-webui
spec:
replicas: 1
selector:
matchLabels:
app: open-webui
template:
metadata:
labels:
app: open-webui
spec:
containers:
- name: open-webui
image: ghcr.io/open-webui/open-webui:main
env:
- name: OPENAI_API_BASE_URL
value: ${svc_address} #前面啟動的vllm master address
- name: ENABLE_OLLAMA_API
value: "false"
ports:
- containerPort: 8080
volumeMounts:
- name: webui-volume
mountPath: /app/backend/data
volumes:
- name: webui-volume
persistentVolumeClaim:
claimName: webui-vllm
其中需要注意以下幾點:
-
指定前面用于保存數據之的PVC,并mount到OpenWebUI保存數據的目錄(/app/backend/data)
-
OpenWebUI服務默認端口為8080
-
使用環境變量指定后端模型服務的API接口(即vllm后端服務集群內訪問方式的信息)
最后,為OpenWebUI創建服務,暴露open-webui的服務
-
創建服務:點擊左側【網絡】->【服務】,選擇對應命名空間,點擊【創建服務】
-
填好后點擊右下角【提交】
訪問服務
-
在【網絡】->【服務】中,找到上一步創建的service外網,在瀏覽器中訪問,按照提示操作
第一次登錄需要設置賬戶/密碼