K8S
基础
示例
推理
运行 Open WebUI + Ollama 类 ChatGPT 轻量推理服务

运行 Open WebUI + Ollama 类 ChatGPT 轻量推理服务

本示例演示如何在 Kubernetes 上部署 Ollama + Open WebUI 提供一个完备轻量推理服务。

前提

存储 PVC

利用持久卷可确保文件持久存在,即使当前运行 Pod 的节点失败。在此示例中,分配了持久卷以保留模型和前端用户数据。

通过 Kubernetes PersistentVolumeClaim 进行持久卷存储的分配,通常称为 PVC,它请求存储大小和要使用的后端存储类型(例如: shared-nvme)。在此示例中,PVC 在 pvc.yaml 文件中定义。

pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ollama
spec:
  storageClassName: shared-nvme
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 20Gi

部署 Deployment

在这个例子中,使用一个 Kubernetes manifests 来部署一个包含 Open WebUI 前端和 Ollama 后端推理服务。

  • metadata.labels 用于为 Pod 设置上标签,selector.matchLabels 用于为 Deployment 选中标签为 name: ollama 的 Pod 进行控制
  • spec.containers 描述多个 Container
    • 一个名字为 ollama 的 Container 用于提供推理 API 服务
      • 把 pvc 挂在 Container 内的 /root/.ollama 目录下存放模型文件
      • 申请并限制 8 vCPU, 24Gi 内存和 1 个 GPU
    • 一个名字为 open-webui 的 Container 用于提供前端服务
      • 通过 localhost:11434 访问到上面的 ollama 服务
      • 把 pvc 挂在 Container 内的 /app/backend/data 目录下存放用户数据
      • 申请并限制 2 vCPU 和 6Gi 内存
  • spec.volumes 描述使用上面创建 pvc 持久卷
  • spec.tolerations 描述容忍 nvidia.com/gpu 污点存在,即可以使用 GPU 节点。通常在 K8S 使用污点以确保 Pod (例如纯 CPU 负载) 不会被调度到不适当节点上。
  • spec.affinity 描述节点亲和性,用于控制偏好或者必须使用那些类型的节点,例如示例必须使用 RTX 4090 节点
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ollama
spec:
  selector:
    matchLabels:
      name: ollama
  template:
    metadata:
      labels:
        name: ollama
    spec:
      containers:
        - name: ollama
          image: ollama/ollama:0.1.48
          env:
            - name: OLLAMA_NUM_PARALLEL
              value: "4"
            - name: OLLAMA_MAX_LOADED_MODELS
              value: "4"
          ports:
            - name: http
              containerPort: 11434
              protocol: TCP
          resources:
            limits:
              cpu: 8
              memory: 24Gi
              nvidia.com/gpu: 1
          volumeMounts:
            - name: ollama
              mountPath: /root/.ollama
        - name: open-webui
          image: ghcr.io/open-webui/open-webui:0.3.7
          env:
            - name: OLLAMA_BASE_URL
              value: "http://localhost:11434"
            - name: HF_ENDPOINT
              value: https://hf-mirror.com
          ports:
            - name: open-webui
              containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 2
              memory: 6Gi
          volumeMounts:
            - name: ollama
              subPath: open-webui
              mountPath: /app/backend/data
      volumes:
        - name: ollama
          persistentVolumeClaim:
            claimName: ollama
      tolerations:
        - key: nvidia.com/gpu
          operator: Exists
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nvidia.com/gpu
                operator: In
                values:
                  - rtx-4090

服务 Service

提供一个集群内的负载均衡器到 Open WebUI 容器实例。

下面示例是:

  1. 使用 selector 选中标签为 name: ollama 的 Pod
  2. Pod 端口名字为 targetPort: open-webui (对应 Deployment 中的定义)
  3. 并以 port: 80 及名字 name: http 提供集群内 type: ClusterIP 的负载均衡服务
service.yaml
apiVersion: v1
kind: Service
metadata:
  name: ollama
spec:
  type: ClusterIP
  selector:
    name: ollama
  ports:
    - port: 80
      name: http
      targetPort: open-webui
      protocol: TCP

入口 Ingress

Ingress 用于暴露应用程序到互联网,从而通过 https 协议访问应用程序。

下面示例是:

  1. rules.host: ollama.c1-389a8e0c7dfc.ing.zw1.paratera.com
  2. 路由 path: /
  3. 到 Service name: ollamaport: 80
  4. 同时开启 spec.tls 并设置自动申请 cert-manager.io/cluster-issuer: zerossl-prod 证书
ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ollama
  annotations:
    cert-manager.io/cluster-issuer: zerossl-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - ollama.c1-389a8e0c7dfc.ing.zw1.paratera.com
      secretName: ollama-tls
  rules:
    - host: ollama.c1-389a8e0c7dfc.ing.zw1.paratera.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: ollama
                port:
                  number: 80

运行示例

  1. 部署

    kubectl apply -f pvc.yaml 
    kubectl apply -f deployment.yaml
    kubectl apply -f service.yaml
    kubectl apply -f ingress.yaml
  2. 查看已创建 Pod

    kubectl get pods

    等待 Pod 进入 Running 状态.

    如果 Pod 一直不能进入 Running,可以通过下面的命令查看 Pod 的详细信息

    kubectl describe pod [pod_id]
  3. 查看 Ingress

    kubectl get ing

    如果 Ingress 准备好,一般在输出 ADDRESS 字段会分配一个 IP 地址

  4. 访问服务

    使用从 Ingress 获取 Hosts 地址,然后在浏览器中访问。

    🎉 恭喜!您已在 Kubernetes 上部署一个带 UI 的 Ollama 推理服务了!