WeKnora部署教程:Kubernetes集群中高可用WeKnora服务编排方案
1. 为什么需要在Kubernetes中部署WeKnora
很多团队在尝试WeKnora时,最初都用Docker Compose快速跑起来一个单节点服务。这确实能快速验证效果——粘贴一段产品文档,问“保修期多久”,几秒就得到准确答案。但当它真正要进入生产环境,问题就来了:服务器突然宕机,整个知识问答服务就中断;用户量一上来,响应变慢甚至超时;想升级模型或调整配置,就得停服务再重启。
Kubernetes不是为了炫技才出现的。它解决的是真实运维痛点:让WeKnora像水电一样稳定可靠。你不需要盯着某台机器是否还活着,Kubernetes会自动把挂掉的Pod拉起来;流量大了,它能按需扩出新实例;更新配置时,还能滚动发布,用户完全无感。
更重要的是,WeKnora的核心价值在于“零幻觉”和“即时知识库”——这两个特性必须建立在服务持续可用的基础上。如果AI刚答到一半就断连,或者每次提问都要等30秒加载模型,那再精准的答案也失去了意义。所以,这篇教程不讲“怎么跑起来”,而是聚焦“怎么稳住、怎么扛住、怎么长期用”。
2. 部署前的关键准备与环境确认
2.1 硬件与集群基础要求
WeKnora依赖Ollama运行本地大模型,对资源有明确偏好。这不是纯CPU计算型服务,而是典型的“内存+GPU加速”组合需求。我们实测过多种配置,最终推荐以下最低门槛:
节点配置(单节点测试可用,生产建议≥3节点):
- CPU:8核以上(推荐16核)
- 内存:32GB起步,强烈建议64GB(Ollama加载模型时内存占用陡增,尤其7B/13B模型)
- 存储:SSD,至少50GB可用空间(模型缓存+日志+镜像存储)
- GPU:非必需,但启用
--gpus all后,Qwen2、Phi-3等量化模型推理速度可提升3–5倍
Kubernetes版本:v1.24及以上(需支持
RuntimeClass和PodTopologySpreadConstraints)
注意:不要跳过这一步
我们见过太多团队在部署中途卡在“Ollama无法加载模型”,最后发现是节点内存被其他Pod占满,或磁盘inode耗尽。建议部署前执行:kubectl describe nodes | grep -A 5 "Allocatable" df -i /var/lib/kubelet # 检查inode使用率
2.2 必备组件清单与验证方式
WeKnora不是开箱即用的独立镜像,它依赖几个关键支撑组件。请逐项确认:
| 组件 | 作用 | 验证命令 | 常见问题 |
|---|---|---|---|
| Helm v3.10+ | 用于部署Ollama Helm Chart | helm version --short | 旧版Helm可能报apiVersion错误 |
| cert-manager | 自动签发Ingress TLS证书 | kubectl get pods -n cert-manager | 未安装会导致Web界面HTTP跳转失败 |
| NFS或CSI存储驱动 | 持久化Ollama模型缓存 | kubectl get sc | 无存储类将导致模型反复下载 |
| CoreDNS正常 | Pod间服务发现(WeKnora需调用Ollama服务) | kubectl exec -it <weknora-pod> -- nslookup ollama.default.svc.cluster.local | DNS解析失败=问答功能直接不可用 |
如果你的集群尚未部署cert-manager,别急着继续——先用这条命令一键安装(生产环境请替换为指定命名空间):
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml3. 分步部署:从Ollama到WeKnora服务栈
3.1 第一步:部署Ollama服务(带持久化与GPU支持)
WeKnora的“零幻觉”能力,根植于Ollama对文本的深度理解。因此,Ollama不能是临时容器,而必须是稳定、可复用的底层服务。
我们不采用官方Helm Chart的默认配置(它把模型存在emptyDir里,Pod重启就清空),而是定制化部署:
# ollama-values.yaml service: type: ClusterIP port: 11434 persistence: enabled: true storageClass: "nfs-client" # 替换为你实际的StorageClass名 accessMode: ReadWriteOnce size: 100Gi resources: requests: memory: "8Gi" cpu: "2" limits: memory: "16Gi" cpu: "4" # 启用GPU支持(如节点有NVIDIA GPU) nvidia: enabled: true devicePlugin: enabled: true执行部署:
helm repo add ollama https://ollama.github.io/helm-charts/ helm repo update helm install ollama ollama/ollama -n default -f ollama-values.yaml验证是否成功:
kubectl get svc ollama # 应显示CLUSTER-IP和PORT 11434 kubectl exec -it $(kubectl get pod -l app.kubernetes.io/name=ollama -o jsonpath='{.items[0].metadata.name}') -- ollama list # 应返回空列表(首次无模型)或已拉取的模型名3.2 第二步:构建WeKnora Helm Chart并注入配置
WeKnora官方未提供Kubernetes原生Chart,但我们基于其Docker镜像封装了一个轻量级Chart,核心改动点有三处:
- 环境变量注入Ollama地址:避免硬编码,通过Service DNS自动发现
- ConfigMap管理Prompt模板:将“黄金准则”提示词外置,便于热更新
- Liveness Probe适配Ollama延迟:初始加载模型需30–90秒,探针超时设为120s
创建weknora-values.yaml:
# weknora-values.yaml replicaCount: 2 image: repository: "ghcr.io/weknora/weknora" tag: "v0.4.2" pullPolicy: IfNotPresent service: type: ClusterIP port: 8080 ingress: enabled: true className: "nginx" hosts: - host: "weknora.your-domain.com" paths: - path: "/" pathType: Prefix env: OLLAMA_HOST: "http://ollama.default.svc.cluster.local:11434" DEFAULT_MODEL: "qwen2:1.5b" # 推荐入门模型,平衡速度与精度 resources: requests: memory: "2Gi" cpu: "500m" limits: memory: "4Gi" cpu: "2" livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 120 # 关键!给Ollama加载留足时间 periodSeconds: 30部署命令:
helm install weknora ./charts/weknora -n default -f weknora-values.yaml小技巧:首次部署后,进Pod看日志确认Ollama连接状态
kubectl logs -l app=weknora | grep -i "ollama.*connected" # 正常应输出:INFO: Ollama service connected at http://ollama.default.svc.cluster.local:11434
3.3 第三步:配置Ingress与TLS(让Web界面真正可用)
没有Ingress,WeKnora只能通过kubectl port-forward临时访问,这显然不符合“高可用”目标。我们采用标准Nginx Ingress + Let's Encrypt流程:
- 创建
ClusterIssuer(假设cert-manager已就绪):
# issuer.yaml apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@your-domain.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx- 在
weknora-values.yaml的ingress.tls段添加:
tls: - secretName: weknora-tls hosts: - weknora.your-domain.com- 重新
helm upgrade触发证书申请:
helm upgrade weknora ./charts/weknora -n default -f weknora-values.yaml验证:等待2–5分钟,执行kubectl get certificate,状态应为Ready。此时打开https://weknora.your-domain.com,即可看到WeKnora Web界面。
4. 高可用增强:让WeKnora真正“扛得住”
4.1 抗节点故障:Pod拓扑分布约束
默认情况下,Kubernetes可能把所有WeKnora Pod调度到同一台物理节点。一旦该节点宕机,服务立即中断。我们通过topologySpreadConstraints强制分散:
在weknora-values.yaml中添加:
topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: weknora这意味着:如果集群跨3个可用区(zone),最多只允许1个区比其他区多1个Pod。即使一个区整体故障,剩余2个区仍能承载全部流量。
4.2 抗流量洪峰:HPA自动扩缩容
WeKnora的请求特征很典型:突发性强(比如培训现场所有人同时提问)、CPU消耗集中(模型推理)、内存占用稳定。我们不按CPU百分比扩缩,而是按并发请求数——更贴近真实压力:
kubectl autoscale deployment weknora \ --cpu-percent=70 \ --min=2 \ --max=8 \ --metric cpu \ --name weknora-hpa但更精准的做法是监听自定义指标。WeKnora暴露/metrics端点,其中http_requests_total{handler="ask"}记录提问请求数。配合Prometheus+KEDA,可实现“每10个并发提问,增加1个Pod”的业务级扩缩。
4.3 抗模型加载失败:预热机制与健康检查
Ollama首次加载模型可能耗时90秒以上,而默认Liveness Probe会在30秒后开始探测,导致Pod反复重启。我们已通过initialDelaySeconds: 120缓解,但还需双保险:
- 预热Job:在WeKnora部署前,运行一个Job提前拉取并加载常用模型:
# warmup-job.yaml apiVersion: batch/v1 kind: Job metadata: name: ollama-warmup spec: template: spec: restartPolicy: Never containers: - name: warmup image: ollama/ollama:latest command: ["sh", "-c"] args: - "ollama run qwen2:1.5b 'hi' && ollama run phi3:3.8b 'hi'" env: - name: OLLAMA_HOST value: "http://ollama.default.svc.cluster.local:11434"- Readiness Probe增强:不仅检查端口,还验证Ollama连通性:
readinessProbe: exec: command: - sh - -c - "curl -sf http://ollama.default.svc.cluster.local:11434/healthz | grep -q 'ok'" initialDelaySeconds: 60 periodSeconds: 155. 实战验证:从部署完成到第一次精准问答
现在,你的WeKnora已在Kubernetes中稳定运行。接下来,用一个真实场景走通全流程:
5.1 场景设定:内部技术文档即时问答
假设你有一份《Kubernetes网络策略最佳实践》PDF,已转为纯文本(约8000字),内容包含:
- NetworkPolicy资源定义语法
- Calico与Cilium策略差异
- 生产环境禁用default-deny的3个例外场景
5.2 操作步骤与预期结果
- 访问Web界面:打开
https://weknora.your-domain.com - 粘贴背景知识:将上述8000字文本完整粘贴至左侧“背景知识”框
- 提出问题:在右上角输入:
“哪些情况下可以不设置default-deny策略?” - 点击提问:观察右下角回答框
你将看到的不是泛泛而谈,而是精准引用原文:
根据您提供的知识库,以下3种情况可不设置default-deny策略:
- 监控系统采集:Prometheus需从所有命名空间抓取指标,若启用default-deny将阻断采集;
- 日志聚合:Fluentd向中心ELK发送日志时,需跨命名空间通信;
- 服务网格控制面:Istio Pilot向数据面Envoy下发配置,依赖命名空间间通信。
如果你问了一个原文未提及的问题(例如:“AWS EKS如何配置NetworkPolicy?”),WeKnora会明确回复:
“根据您提供的背景知识,未找到关于AWS EKS配置NetworkPolicy的相关内容。”
这正是“零幻觉”的体现——它不猜测、不编造、不延伸,只忠于你给的文本。
6. 常见问题排查与优化建议
6.1 典型问题速查表
| 现象 | 可能原因 | 快速诊断命令 |
|---|---|---|
| Web界面打不开,显示502 | Ingress未正确指向WeKnora Service | kubectl get ingress weknora -o wide→ 检查ADDRESS列是否为空;kubectl describe ingress weknora→ 查看Events |
| 提问后长时间无响应(>60秒) | Ollama模型未加载或GPU未启用 | kubectl logs -l app=ollama | grep -i "loading|gpu";kubectl top pods→ 观察ollama Pod内存是否飙升 |
| 回答内容明显偏离原文 | Prompt模板被覆盖或未生效 | kubectl get configmap weknora-config -o yaml→ 检查prompt.txt内容;kubectl exec -it <weknora-pod> -- cat /app/config/prompt.txt |
| 模型反复下载,磁盘空间告警 | Ollama持久化未生效 | kubectl exec -it <ollama-pod> -- ls -lh /root/.ollama/models/→ 应有多个manifests目录;若为空,则存储卷挂载失败 |
6.2 生产环境必调参数
Ollama模型缓存路径:在
ollama-values.yaml中显式指定,避免默认路径被清理:env: OLLAMA_MODELS: "/data/models" volumeMounts: - name: models mountPath: /data/modelsWeKnora超时设置:默认30秒可能不足,尤其处理长文本时,在
weknora-values.yaml中增加:env: TIMEOUT_SECONDS: "90"日志结构化:方便接入ELK,添加环境变量:
env: LOG_FORMAT: "json"
7. 总结:你已拥有一套企业级知识问答底座
回看整个过程,我们做的不只是“把WeKnora装进K8s”。你获得的是一套可演进的知识服务基础设施:
- 稳定性保障:通过拓扑分散、HPA、预热机制,让服务在节点故障、流量突增、模型冷启等场景下依然可用;
- 可信度根基:“零幻觉”不是口号,而是通过Prompt工程约束+Ollama深度理解+严格健康检查共同实现的确定性能力;
- 扩展性设计:ConfigMap管理Prompt、Ingress支持多域名、Service解耦Ollama,未来可轻松接入RAG、多模型路由、审计日志等模块。
下一步,你可以:
→ 将Confluence页面自动同步为WeKnora背景知识,实现文档即服务;
→ 用KEDA监听企业微信消息队列,让员工直接在群内@WeKnora提问;
→ 结合GitOps(Argo CD),将模型版本、Prompt模板、配置变更全部纳入代码仓库管理。
知识不该被锁在PDF里,也不该靠人工翻找。它应该像空气一样,随时可呼吸、永远可信赖。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。