WeKnora Helm Chart 部署指南:在 Kubernetes 上部署 AI 知识库 RAG 平台
【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora
WeKnora 是一个开源的 AI 知识库 RAG 平台,将文档解析、向量检索与 BM25 混合检索、LLM 对话集成和多租户加密能力整合为一体。本指南基于仓库中 helm/README.md 及helm/目录下的 Chart 源码,系统讲解如何使用 Helm 3 在 Kubernetes 集群上一键部署 WeKnora 全套组件(后端 API、前端 UI、Docreader 文档解析服务、PostgreSQL/ParadeDB 与 Redis),并深入解析每个配置参数的作用、模板注入逻辑与生产级安全实践。读完本文,你将掌握从快速安装、接入外部 LLM、启用 Ingress 与可选组件(MinIO/Neo4j/Qdrant),到升级、卸载与排障的完整运维闭环。
Chart 概览与组件架构
helm/是一个标准 Helm v2(apiVersion: v2)Application 类型 Chart,当前 Chart 版本为0.1.0,对应应用版本appVersion: "v0.8.0",并要求 Kubernetes 版本不低于 1.25(见 helm/Chart.yaml)。它把一个完整的 WeKnora 知识库平台拆分为以下几个可独立启停的组件:
- Frontend:基于 Vue.js 的 Web UI(
wechatopenai/weknora-ui),由 Nginx 提供静态资源并反向代理后端; - App(Backend):基于 Go/Gin 的 API 服务器(
wechatopenai/weknora-app),对外暴露 8080 端口,负责知识库管理、检索、会话与 LLM 调用; - Docreader:文档解析服务(
wechatopenai/weknora-docreader),通过 gRPC 协议(默认docreader:50051)向 App 提供 PDF、DOCX、HTML 等多格式解析能力; - PostgreSQL(ParadeDB):默认使用
paradedb/paradedb镜像,在 PostgreSQL 之上提供向量检索(pgvector 类能力)与 BM25 全文检索,是默认的检索后端; - Redis:用作流管理(Stream Manager)与异步任务队列(Async Queue),例如文档处理任务、会话流式输出等。
各组件通过集群内 Service 名互相引用,整体流量走向如下(来自 helm/README.md 的架构示意):
┌─────────────┐ │ Ingress │ └──────┬──────┘ │ ┌───────────────┴───────────────┐ │ │ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ Frontend │ │ Backend │ │ (Vue.js) │ │ (Go/Gin) │ └─────────────┘ └──────┬──────┘ │ ┌──────────────────────┼──────────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Docreader │ │ PostgreSQL │ │ Redis │ │ (gRPC) │ │ (ParadeDB) │ │ (Queue) │ └─────────────┘ └─────────────┘ └─────────────┘前置条件
- Kubernetes 1.25+:Chart 在
Chart.yaml中声明了kubeVersion: ">=1.25.0-0"的硬性约束; - Helm 3.10+:支持 Chart 的模板语法与
lookup函数; - 底层基础设施需支持 PV Provisioner:PostgreSQL、Redis、上传文件数据都需要持久化存储;
- Ingress Controller(推荐 nginx-ingress):如需从集群外访问 Web UI,需要启用 Ingress。
快速开始:一条命令拉起全套组件
首次安装只需提供三个必填 Secret(数据库密码、Redis 密码、JWT 签名密钥):
helm install weknora ./helm \ --namespace weknora \ --create-namespace \ --set secrets.dbPassword=<your-db-password> \ --set secrets.redisPassword=<your-redis-password> \ --set secrets.jwtSecret=<your-jwt-secret>安装完成后,Helm 会在终端输出 helm/templates/NOTES.txt 渲染的提示信息,包括:
- 未启用 Ingress 时,使用端口转发访问:
kubectl port-forward svc/frontend -n weknora 8080:80 # 然后打开 http://localhost:8080 - 已部署组件清单(含各组件镜像);
- 连接 LLM 的环境变量示例;
- 排障常用命令。
注意:
secrets.dbPassword、secrets.redisPassword、secrets.jwtSecret三个参数在 helm/templates/secrets.yaml 中通过required函数强校验,缺失时helm install会直接报错终止,这是 Chart 主动拒绝“裸奔部署”的设计。
安装场景进阶
启用 Ingress 对外暴露
helm install weknora ./helm \ --namespace weknora \ --create-namespace \ --set ingress.enabled=true \ --set ingress.host=weknora.example.com \ --set ingress.tls.enabled=true \ --set ingress.tls.secretName=weknora-tls \ --set secrets.dbPassword=secure-password \ --set secrets.redisPassword=secure-password \ --set secrets.jwtSecret=$(openssl rand -base64 32)从 helm/templates/ingress.yaml 可以看到路由规则的设计:
/api前缀路径路由到名为app的后端 Service(必须放在前面,因为更具体的路径优先匹配);/兜底路由到名为frontend的 Service;- 默认携带一组对知识库平台非常关键的 Nginx 注解(定义于 helm/values.yaml 的
ingress.annotations):annotations: nginx.ingress.kubernetes.io/proxy-body-size: "100m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"其中
proxy-body-size: 100m保证大文件上传不被 Nginx 拦截,proxy-read-timeout/send-timeout: 3600为长耗时的 LLM 流式问答留足通道。
接入外部 LLM(以 Ollama 为例)
WeKnora 本身不包含模型推理能力,需要对接 LLM 后端。Chart 通过app.extraEnv向 App 容器注入任意环境变量:
helm install weknora ./helm \ --namespace weknora \ --create-namespace \ --set app.extraEnv[0].name=OLLAMA_BASE_URL \ --set app.extraEnv[0].value=http://ollama.ollama:11434 \ --set app.extraEnv[1].name=INIT_LLM_MODEL_NAME \ --set app.extraEnv[1].value=qwen2.5:7b \ --set secrets.dbPassword=secure-password \ --set secrets.redisPassword=secure-password \ --set secrets.jwtSecret=$(openssl rand -base64 32)app.extraEnv的注入实现在 helm/templates/app.yaml 末尾:{{- with .Values.app.extraEnv }}会将列表原样渲染为容器的 env 条目。结合 docker-compose.yml 中OLLAMA_BASE_URL、INIT_LLM_MODEL_NAME等变量的定义,可以推断 WeKnora 的模型层兼容 Ollama(本地)、OpenAI API 兼容端点、Qwen/DeepSeek 等常见 LLM 服务,安装后也可在 Web 界面的模型设置中继续补充模型配置。
生产环境安装:使用 values 文件
生产部署建议把配置固化为values-production.yaml文件:
# values-production.yaml global: storageClass: "fast-ssd" app: replicaCount: 3 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2 memory: 4Gi postgresql: persistence: size: 100Gi ingress: enabled: true host: weknora.company.com tls: enabled: true secretName: weknora-tls secrets: existingSecret: weknora-secrets # Use pre-created secrethelm install weknora ./helm \ --namespace weknora \ --create-namespace \ -f values-production.yaml该示例综合了四个生产要点:指定高性能存储类(global.storageClass)、扩展 App 副本数并设置资源上限(滚动更新策略maxSurge: 1+maxUnavailable: 0,见 helm/templates/app.yaml)、扩大数据库 PVC 容量、复用预创建的 Secret 而非在 values 中明文写密码。
配置参数全解
以下参数表完整继承自 helm/README.md 的 Configuration 章节,并结合 helm/values.yaml 的默认值与注释进行扩充。
Global 全局参数
| 参数 | 描述 | 默认值 |
|---|---|---|
global.storageClass | 所有 PVC 使用的存储类;设为-表示使用集群默认存储类 | "" |
global.imagePullSecrets | 私有镜像仓库的拉取凭证 | [] |
global.podSecurityContext | Pod 级安全上下文(默认启用seccompProfile: RuntimeDefault) | 见 values.yaml |
global.containerSecurityContext | 容器级安全上下文(默认allowPrivilegeEscalation: false) | 见 values.yaml |
ServiceAccount
| 参数 | 描述 | 默认值 |
|---|---|---|
serviceAccount.create | 是否创建 ServiceAccount | true |
serviceAccount.name | ServiceAccount 名称(留空自动生成) | "" |
serviceAccount.annotations | ServiceAccount 注解 | {} |
serviceAccount.name的解析逻辑定义在 helm/templates/_helpers.tpl 的weknora.serviceAccountName中:创建时默认取 release 全名,不创建时回退到default。此外 values.yaml 还提供automountServiceAccountToken(默认false)与labels等未在 README 中列出的控制项。
App(后端)
| 参数 | 描述 | 默认值 |
|---|---|---|
app.enabled | 是否启用后端 | true |
app.replicaCount | 副本数 | 1 |
app.image.repository | 镜像仓库 | wechatopenai/weknora-app |
app.image.tag | 镜像标签 | ""(使用appVersion) |
app.resources | 资源请求与限制 | requests: 100m/256Mi,limits: 1/1Gi |
app.env | 内置环境变量(见下文) | 见 values.yaml |
app.extraEnv | 附加环境变量 | [] |
值得展开的是app.env中的一组关键运行参数(均来自 helm/values.yaml):
| 环境变量 | 作用 | Chart 默认值 |
|---|---|---|
GIN_MODE | Gin 运行模式,release为生产模式 | release |
RETRIEVE_DRIVER | 检索引擎驱动,可选postgres、elasticsearch_v7、elasticsearch_v8、qdrant等 | postgres |
STORAGE_TYPE | 文件存储类型,可选local、minio、cos、tos、s3等 | local |
LOCAL_STORAGE_BASE_DIR | 本地文件存储目录(对应 PVC 挂载点/data/files) | /data/files |
STREAM_MANAGER_TYPE | 流管理器类型 | redis |
CONCURRENCY_POOL_SIZE | 文档处理并发池大小 | 5 |
AUTO_RECOVER_DIRTY | 是否自动回收卡在 processing 状态的脏任务 | true |
WEKNORA_SANDBOX_DOCKER_ENABLED | 是否启用 Docker 沙箱(开启等同获得宿主机 root 权限,默认关闭) | false |
在 helm/templates/app.yaml 中,App 容器还硬编码了若干与集群内 Service 强绑定的连接信息,理解这些固定值有助于排查问题:
DB_HOST=postgres、DB_PORT=5432,DB_USER/DB_PASSWORD/DB_NAME通过secretKeyRef从 Secret 注入;REDIS_ADDR=redis:6379、REDIS_DB=0、REDIS_PREFIX=stream:,密码同样取自 Secret;DOCREADER_ADDR=docreader:50051,指向 Docreader 的 gRPC Service;JWT_SECRET、SYSTEM_AES_KEY均通过secretKeyRef引用 Secret;- 当
neo4j.enabled=true时自动注入NEO4J_ENABLE=true、NEO4J_URI=bolt://neo4j:7687及从 Secret 读取的 Neo4j 凭证。
Frontend
| 参数 | 描述 | 默认值 |
|---|---|---|
frontend.enabled | 是否启用前端 | true |
frontend.replicaCount | 副本数 | 1 |
frontend.image.repository | 镜像仓库 | wechatopenai/weknora-ui |
frontend.image.tag | 镜像标签 | latest |
helm/templates/frontend.yaml 会注入APP_HOST(默认app)与APP_PORT(默认后端 Service 端口 8080)两个环境变量,让 Nginx 容器知道如何反代后端;同时以emptyDir挂载/var/cache/nginx与/var/run,满足 Nginx 对可写临时目录的需求。Service 名固定为frontend,被 Ingress 引用。
PostgreSQL(ParadeDB)
| 参数 | 描述 | 默认值 |
|---|---|---|
postgresql.enabled | 是否启用 PostgreSQL | true |
postgresql.image.repository | 镜像仓库 | paradedb/paradedb |
postgresql.image.tag | 镜像标签 | v0.18.9-pg17 |
postgresql.persistence.enabled | 是否启用持久化 | true |
postgresql.persistence.size | PVC 容量 | 10Gi |
helm/templates/postgres.yaml 中数据库使用Recreate 更新策略(避免多副本同时挂载同一数据卷造成数据损坏),POSTGRES_USER/PASSWORD/DB全部取自 Secret,数据目录为/var/lib/postgresql/data/pgdata,就绪/存活探针均使用pg_isready。
Redis
| 参数 | 描述 | 默认值 |
|---|---|---|
redis.enabled | 是否启用 Redis | true |
redis.image.repository | 镜像仓库 | redis |
redis.image.tag | 镜像标签 | 7-alpine |
redis.persistence.enabled | 是否启用持久化 | true |
redis.persistence.size | PVC 容量 | 1Gi |
helm/templates/redis.yaml 使用redis-server --requirepass $(REDIS_PASSWORD) --appendonly yes --dir /data启动:开启 AOF 持久化,密码来自 Secret,探针通过redis-cli -a $REDIS_PASSWORD ping | grep PONG验证鉴权后的连通性。
Ingress
| 参数 | 描述 | 默认值 |
|---|---|---|
ingress.enabled | 是否启用 Ingress | false |
ingress.className | IngressClass 名称 | nginx |
ingress.host | 域名 | weknora.example.com |
ingress.tls.enabled | 是否启用 TLS | false |
ingress.tls.secretName | TLS 证书 Secret 名称 | "" |
Secrets
| 参数 | 描述 | 默认值 |
|---|---|---|
secrets.dbUser | 数据库用户名 | postgres |
secrets.dbPassword | 数据库密码 | ""(必填) |
secrets.dbName | 数据库名 | weknora |
secrets.redisPassword | Redis 密码 | ""(必填) |
secrets.jwtSecret | JWT 签名密钥 | ""(必填) |
secrets.existingSecret | 使用已有 Secret 而不是自动创建 | "" |
values.yaml 中还有一些 README 未列出的 Secret 细节值得关注:
secrets.redisUsername:Redis 6.0+ ACL 用户名(可选);secrets.systemAesKey:数据库敏感字段 AES-256 加密主密钥,必须恰好为 32 字节。加密范围覆盖租户 API Key、模型 API Key、向量库凭证、Web Search Provider 密钥、WeKnoraCloud AppSecret 等。若留空,首次安装时会随机生成 32 位值。
可选组件(对应 docker-compose profiles)
| 参数 | 描述 | 默认值 |
|---|---|---|
minio.enabled | 启用 MinIO 作为 S3 兼容存储 | false |
neo4j.enabled | 启用 Neo4j 知识图谱(GraphRAG) | false |
qdrant.enabled | 启用 Qdrant 向量数据库 | false |
这三个开关与 docker-compose.yml 中的minio、neo4j、qdrantprofile 一一对应。启用细节:
- MinIO:需同时设置
minio.rootPassword(以及可选的rootUser,默认minioadmin),持久化默认 20Gi; - Neo4j:启用后 Chart 自动向 App 注入
NEO4J_ENABLE=true并创建包含NEO4J_USERNAME/NEO4J_PASSWORD的 Secret 条目,此时必须设置neo4j.password(否则required校验失败)。NEO4J_ENABLE是知识图谱的唯一开关,旧的ENABLE_GRAPH_RAG已废弃、Go 主应用不再读取(见 helm/templates/app.yaml 与 helm/templates/secrets.yaml 的注释)。Neo4j 镜像标签为2025.10.1,与 docker-compose 保持一致; - Qdrant:作为备选向量库,持久化默认 10Gi。启用后可配合
app.extraEnv将RETRIEVE_DRIVER指向 Qdrant。
源码视角:模板实现的关键设计
依赖硬编码的固定 Service 名
从 helm/templates/app.yaml、helm/templates/postgres.yaml、helm/templates/redis.yaml、helm/templates/docreader.yaml 的 Service 定义可以看到一个共同设计:Service 名称被刻意固定为app、postgres、redis、docreader、frontend,而不是标准的release-name-组件名命名。模板注释明确说明这是为了让 App 容器的DB_HOST、REDIS_ADDR、DOCREADER_ADDR以及前端 Nginx 和 Ingress 的反代目标可以稳定解析。这意味着在同一 Namespace 内多次部署时需要注意 Service 名冲突。
Secret 的滚动升级安全
helm/templates/secrets.yaml 是模板中最值得研读的部分之一。它通过 Helm 内置的lookup函数实现“随机密钥的幂等生成”:
{{- $existing := lookup "v1" "Secret" .Release.Namespace $secretName }} {{- $existingSystemKey := "" }} {{- if and $existing $existing.data }} {{- if index $existing.data "SYSTEM_AES_KEY" }} {{- $existingSystemKey = index $existing.data "SYSTEM_AES_KEY" | b64dec }} {{- end }} {{- end }} {{- $systemAesKey := .Values.secrets.systemAesKey | default $existingSystemKey | default (randAlphaNum 32) }}其逻辑是:优先使用用户显式设置的systemAesKey;未设置则回读集群中已存在的 Secret 里的SYSTEM_AES_KEY并继续复用;两者都为空时才生成新的随机值。这保证了每次helm upgrade不会重新滚动加密主密钥——否则旧密钥加密的数据(如租户 API Key)将永久无法解密,界面上会显示enc:v1:...密文。
命名与标签规范
helm/templates/_helpers.tpl 提供了完整的命名与标签模板:weknora.fullname(release 名与 chart 名拼接、截断 63 字符)、weknora.componentLabels(统一注入helm.sh/chart、app.kubernetes.io/version、app.kubernetes.io/managed-by、app.kubernetes.io/part-of: weknora与组件级app.kubernetes.io/component标签)。排障时可以直接利用这些标签筛选资源,例如:
kubectl get pods -n weknora -l app.kubernetes.io/instance=weknora kubectl logs -n weknora -l app.kubernetes.io/component=app -f存储类、镜像与安全上下文的合并规则
weknora.storageClass(helm/templates/_helpers.tpl)约定:global.storageClass为空时不写storageClassName(使用集群默认存储类),设为-时显式写入空字符串,其余情况写入指定的存储类名。Pod 安全上下文则遵循“组件覆盖合并全局默认”的规则:app组件可在app.podSecurityContext中覆盖global.podSecurityContext,而 postgres/redis/frontend/docreader 直接使用全局值。
安全最佳实践
Secret 管理:永远不要把密钥提交到 Git
Chart 提供三种可选方式:
- Helm
--set标志(仅限测试环境):helm install weknora ./helm --set secrets.dbPassword=xxx - External Secrets Operator(生产推荐),把云厂商 Secret Manager 同步为集群 Secret 后复用:
secrets: existingSecret: weknora-external-secret使用
existingSecret时,Chart 不再创建自己的 Secret(helm/templates/secrets.yaml 最外层即{{- if not .Values.secrets.existingSecret }}守卫),要求 Secret 内必须包含DB_USER、DB_PASSWORD、DB_NAME、REDIS_USERNAME、REDIS_PASSWORD、JWT_SECRET、SYSTEM_AES_KEY这些键,各组件模板通过secretKeyRef按键名读取; - Sealed Secrets(GitOps 场景),把 Secret 加密成可入库的 SealedSecret:
kubeseal < secret.yaml > sealed-secret.yaml
Pod 安全
Chart 遵循 CNCF 安全最佳实践(定义于 helm/values.yaml 的 global 安全上下文):
- 默认不启用
runAsNonRoot——因为官方镜像(nginx、postgres、redis)默认以 root 运行,强制非 root 反而导致启动失败(values.yaml 中对此有专门注释说明); - 所有容器默认
allowPrivilegeEscalation: false,禁止提权; - Pod 默认启用
seccompProfile: RuntimeDefault; - ServiceAccount 默认
automountServiceAccountToken: false,降低容器内被窃取 API 凭证的风险; - 文件系统写权限按需最小化:仅 App 容器挂载可写的
/data/filesPVC,前端 Nginx 只挂载两个emptyDir临时目录,数据库与 Redis 各挂载各自的数据卷。
升级与卸载
升级
helm upgrade weknora ./helm \ --namespace weknora \ --reuse-values--reuse-values会保留上一次安装时通过--set传入的值,避免升级时因未重复传参而覆盖生产配置。由于 Secret 模板具备“lookup 复用旧密钥”的能力,升级不会导致SYSTEM_AES_KEY轮换(详见上文模板解析)。
卸载
helm uninstall weknora --namespace weknora # 可选:清理 PVC kubectl delete pvc -n weknora -l app.kubernetes.io/instance=weknoraHelm 默认不会删除 PVC(避免误删数据),需要按 release 标签显式清理持久化数据。
故障排查指南
基础排查
# 查看 Pod 状态 kubectl get pods -n weknora # 后端日志 kubectl logs -n weknora -l app.kubernetes.io/component=app -f # 前端日志 kubectl logs -n weknora -l app.kubernetes.io/component=frontend -f由于模板统一注入了组件标签,app.kubernetes.io/component可以精准筛选app、frontend、docreader、database(PostgreSQL)、cache(Redis)等组件。
常见问题
Pod 一直处于 Pending
- 检查 PVC 是否已绑定:
kubectl get pvc -n weknora - 确认存储类存在:
kubectl get sc
Connection refused 错误
- 等待所有 Pod 变为 Ready(App 依赖数据库、Redis、Docreader 全部就绪)
- 检查 Service 端点是否正常:
kubectl get endpoints -n weknora
数据库连接错误
- 核对 Secret 中的账号密码是否与
secrets.*配置一致 - 查看 PostgreSQL 日志:
kubectl logs -n weknora -l app.kubernetes.io/component=database
LLM 无法调用
- 通过
--set app.extraEnv[...]确认OLLAMA_BASE_URL等变量已正确注入(可用kubectl exec进入容器env验证); - 若使用了 Ollama,确认集群网络可以连通 Ollama 的 Service 地址。
从 docker-compose 到 Kubernetes 的迁移对照
这份 Chart 与仓库根目录的 docker-compose.yml 存在清晰的对应关系,理解这种映射有助于快速定位“compose 能跑、K8s 不行”的问题:
| docker-compose 服务 | Helm 组件 | 说明 |
|---|---|---|
frontend(weknora-ui) | frontend.* | Nginx 反代,注入APP_HOST/APP_PORT |
app(weknora-app) | app.* | 后端 API,挂载/data/files |
docreader | docreader.* | gRPC 文档解析,探针用grpc_health_probe |
postgres(paradedb/paradedb) | postgresql.* | 默认检索后端(注意 compose 用v0.22.2-pg17,Chart 默认v0.18.9-pg17,可按需覆盖postgresql.image.tag) |
redis | redis.* | 队列与流管理 |
minio/neo4j/qdrant(profile) | minio.*/neo4j.*/qdrant.* | 可选组件,默认关闭 |
两种部署方式共享同一套环境变量语义(如RETRIEVE_DRIVER、STORAGE_TYPE、SYSTEM_AES_KEY),因此迁移时可以把成熟的 compose.env经验直接映射为app.extraEnv。
结语
WeKnora 的 Helm Chart 是一个组件划分清晰、生产化考虑周全的部署方案:固定 Service 名的“零配置互联”设计降低了上手门槛,lookup幂等密钥保证了升级安全,可选的 MinIO/Neo4j/Qdrant 组件让部署拓扑可以随知识图谱、向量检索等能力需求平滑演进。本文涉及的完整参数表可直接参考 helm/values.yaml,模板实现细节可查阅 helm/templates/ 下的各个渲染文件;若需要进一步了解平台自身的能力(如文档解析、混合检索、RBAC 与加密机制),可以继续阅读仓库根目录的 README.md 与 docs 目录下的相关文档。
【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考