在 TKE 上部署 AI 大模型(以DeepSeek-R1為例)
概述
本文介紹如何在 TKE 上部署 AI 大模型,以 DeepSeek-R1 為例。
部署思路
使用 Ollama 運行 AI 大模型,再通過 OpenWebUI 暴露一個聊天交互的界面,OpenWebUI 會調(diào)用 ollama 提供的 API 來與大模型交互。
Ollama 與 OpenWebUI 介紹
Ollama 是一個運行大模型的工具,可以看成是大模型領(lǐng)域的 Docker,可以下載所需的大模型并暴露 API。
OpenWebUI 是一個大模型的 Web UI 交互工具,支持 Ollama,即調(diào)用 Ollama 暴露的 API 實現(xiàn)與大模型交互:
圖片
AI 大模型數(shù)據(jù)如何存儲?
AI 大模型通常占用體積較大,直接打包到容器鏡像不太現(xiàn)實,如果啟動時通過 initContainers 自動下載又會導(dǎo)致啟動時間過長,因此建議使用共享存儲來掛載 AI 大模型。
在騰訊云上可使用 CFS 來作為共享存儲,CFS 的性能和可用性都非常不錯,適合 AI 大模型的存儲。本文將使用 CFS 來存儲 AI 大模型。
準(zhǔn)備 CFS 存儲
在【組建管理】中的【存儲】找到 CFS-Turbo 或 CFS 插件并安裝:
圖片
CFS-Turbo 的性能更強,讀寫速度更快,也更貴,如果希望大模型運行速度更快,可以考慮使用 CFS-Turbo。
新建 StorageClass:
圖片
- 選項較多,所以該示例通過 TKE 控制臺來創(chuàng)建 PVC。如希望通過 YAML 來創(chuàng)建,可先用控制臺創(chuàng)建一個測試 PVC,再復(fù)制出生成的 YAML。
- Provisioner 選 文件存儲CFS。
- 存儲類型 建議選 性能存儲,讀寫速度比 標(biāo)準(zhǔn)存儲 更快。
新建 GPU 節(jié)點池
在 TKE 控制臺的【節(jié)點管理】-【節(jié)點池】中點擊【新建】,如果【原生節(jié)點】或【普通節(jié)點】,機型在【GPU 機型】中選擇一個沒售罄的機型;如果選【超級節(jié)點】則無需選擇機型(在部署的時候通過注解指定 GPU 類型)。
確認 GPU 驅(qū)動和所需 CUDA 版本
可隨便買一臺對應(yīng)節(jié)點池機型的云服務(wù)器,上去執(zhí)行 nvidia-smi 命令,查看 GPU 驅(qū)動版本。
在 nvidia 官網(wǎng)的 CUDA Toolkit Release Notes (https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html) 中,查找適合對應(yīng) GPU 驅(qū)動版本的 CUDA 版本。
編譯 ollama 鏡像
準(zhǔn)備 Dockerfile:
FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04
RUN apt update -y && apt install -y curl
RUN curl -fsSL https://ollama.com/install.sh | sh
基礎(chǔ)鏡像使用 nvidia/cuda,具體使用哪個 tag 可根據(jù)前面確認的 cuda 版本來定。這里是所有 tag 的列表: https://hub.docker.com/r/nvidia/cuda/tags。
編譯并上傳鏡像:
docker build -t imroc/ollama:cuda11.8-ubuntu22.04 .
docker push imroc/ollama:cuda11.8-ubuntu22.04
注意修改成自己的鏡像名稱。
創(chuàng)建 PVC
創(chuàng)建一個 CFS 類型的 PVC,用于存儲 AI 大模型:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ai-model
labels:
app: ai-model
spec:
storageClassName: deepseek
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
- 注意替換 storageClassName。
- 對于 CFS 來說,storage 大小無所謂,可隨意指定,按實際占用空間付費的。
再創(chuàng)建一個 PVC 給 OpenWebUI 用,可使用同一個 storageClassName:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webui
labels:
app: webui
spec:
accessModes:
- ReadWriteMany
storageClassName: deepseek
resources:
requests:
storage: 100Gi
使用 Job 下載 AI 大模型
下發(fā)一個 Job,將需要用的 AI 大模型下載到 CFS 共享存儲中:
apiVersion: batch/v1
kind: Job
metadata:
name: pull-model
labels:
app: pull-model
spec:
template:
metadata:
name: pull-model
labels:
app: pull-model
spec:
containers:
- name: pull-model
image: imroc/ollama:cuda11.8-ubuntu22.04
env:
- name: LLM_MODEL
value: deepseek-r1:7b
command:
- bash
- -c
- |
set -ex
ollama serve &
sleep 5
ollama pull $LLM_MODEL
volumeMounts:
- name: data
mountPath: /root/.ollama
volumes:
- name: data
persistentVolumeClaim:
claimName: ai-model
restartPolicy: OnFailure
- 使用之前我們編譯好的 ollama 鏡像,執(zhí)行一個腳本去下載 AI 大模型,本例中下載的是 deepseek-r1:7b,完整列表在 https://ollama.com/search,修改 LLM_MODEL 以替換大語言模型。
- ollama 的模型數(shù)據(jù)存儲在 /root/.ollama 目錄下,掛載 CFS 類型的 PVC 到該路徑。
部署 ollama
通過 Deployment 部署 ollama:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama
labels:
app: ollama
spec:
selector:
matchLabels:
app: ollama
replicas: 1
template:
metadata:
labels:
app: ollama
annotations:
eks.tke.cloud.tencent.com/gpu-type: V100
spec:
containers:
- name: ollama
image: imroc/ollama:cuda11.8-ubuntu22.04
imagePullPolicy: IfNotPresent
command: ["ollama", "serve"]
env:
- name: OLLAMA_HOST
value: ":11434"
resources:
requests:
cpu: 2000m
memory: 2Gi
nvidia.com/gpu: "1"
limits:
cpu: 4000m
memory: 4Gi
nvidia.com/gpu: "1"
ports:
- containerPort: 11434
name: ollama
volumeMounts:
- name: data
mountPath: /root/.ollama
volumes:
- name: data
persistentVolumeClaim:
claimName: ai-model
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: ollama
spec:
selector:
app: ollama
type: ClusterIP
ports:
- name: server
protocol: TCP
port: 11434
targetPort: 11434
- ollama 的模型數(shù)據(jù)存儲在 /root/.ollama 目錄下,掛載已經(jīng)下載好 AI 大模型的 CFS 類型 PVC 到該路徑。
- ollama 監(jiān)聽 11434 端口暴露 API,定義 Service 方便后續(xù)被 OpenWebUI 調(diào)用。
- ollama 默認監(jiān)聽的是回環(huán)地址(127.0.0.1),指定 OLLAMA_HOST 環(huán)境變量,強制對外暴露 11434 端口。
- 運行大模型需要使用 GPU,因此在 requests/limits 中指定了 nvidia.com/gpu 資源,以便讓 Pod 調(diào)度到 GPU 機型并分配 GPU 卡使用。
- 如果希望大模型跑在超級節(jié)點,需通過 Pod 注解 eks.tke.cloud.tencent.com/gpu-type 指定 GPU 類型;若不希望調(diào)度到超級節(jié)點則刪除該注解。
部署 OpenWebUI
使用 Deployment 部署 OpenWebUI,并定義 Service 方便后續(xù)對外暴露訪問:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webui
spec:
replicas: 1
selector:
matchLabels:
app: webui
template:
metadata:
labels:
app: webui
spec:
containers:
- name: webui
image: imroc/open-webui:main # docker hub 中的 mirror 鏡像,長期自動同步,可放心使用
env:
- name: OLLAMA_BASE_URL
value: http://ollama:11434 # ollama 的地址
- name: HF_HUB_OFFLINE
value: "1"
- name: ENABLE_OPENAI_API
value: "false"
tty: true
ports:
- containerPort: 8080
resources:
requests:
cpu: "500m"
memory: "500Mi"
limits:
cpu: "1000m"
memory: "1Gi"
volumeMounts:
- name: webui-volume
mountPath: /app/backend/data
volumes:
- name: webui-volume
persistentVolumeClaim:
claimName: webui
---
apiVersion: v1
kind: Service
metadata:
name: webui
labels:
app: webui
spec:
type: ClusterIP
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: webui
- OLLAMA_BASE_URL 是 ollama 的地址,填 ollama 的 service 訪問地址。
- ENABLE_OPENAI_API 填 false,因為我們使用的是 ollama,不需要使用 openai api,禁用它避免啟動時因國內(nèi)連不上 openapi 地址而無法加載模型(現(xiàn)象是登錄 OpenWebUI 返回空白頁)。
- OpenWebUI 的數(shù)據(jù)存儲在 /app/backend/data 目錄(如賬號密碼、聊天歷史等數(shù)據(jù)),我們掛載 PVC 到這個路徑。
暴露 OpenWebUI 并與模型對話
如果只是本地測試,可以使用 kubectl port-forward 暴露服務(wù):
kubectl port-forward service/webui 8080:8080
在瀏覽器中訪問 http://127.0.0.1:8080 即可。
你還可以通過 Ingress 或 Gateway API 來暴露,我這里通過 Gateway API 來暴露(需安裝 Gateway API 的實現(xiàn),如 TKE 應(yīng)用市場中的 EnvoyGateway,具體 Gateway API 用法參考 https://gateway-api.sigs.k8s.io/guides/):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ai
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: envoy-gateway-system
name: imroc
sectionName: https
hostnames:
- "ai.imroc.cc"
rules:
- backendRefs:
- group: ""
kind: Service
name: webui
port: 8080
- parentRefs 引用定義好的 Gateway(通常一個 Gateway 對應(yīng)一個 CLB)。
- hostnames 替換為你自己的域名,確保域名能正常解析到 Gateway 對應(yīng)的 CLB 地址。
- backendRefs 指定 OpenWebUI 的 Service。
最后在瀏覽器訪問 hostnames 中的地址即可。
首次進入 OpenWebUI 會提示創(chuàng)建管理員賬號密碼,創(chuàng)建完畢后即可登錄,然后默認會使用前面下載好的大模型進行對話。
圖片