WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
apiVersion: v2
|
||||
name: weknora
|
||||
description: |
|
||||
WeKnora - AI-powered Knowledge RAG Platform for building intelligent knowledge bases
|
||||
with document parsing, vector search, and LLM integration.
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "v0.8.0"
|
||||
kubeVersion: ">=1.25.0-0"
|
||||
home: https://github.com/Tencent/WeKnora
|
||||
icon: https://raw.githubusercontent.com/Tencent/WeKnora/main/docs/images/logo.png
|
||||
sources:
|
||||
- https://github.com/Tencent/WeKnora
|
||||
keywords:
|
||||
- ai
|
||||
- rag
|
||||
- knowledge-base
|
||||
- llm
|
||||
- document-parsing
|
||||
- vector-search
|
||||
- chatbot
|
||||
maintainers:
|
||||
- name: WeKnora Community
|
||||
url: https://github.com/Tencent/WeKnora
|
||||
annotations:
|
||||
artifacthub.io/license: MIT
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
# WeKnora Helm Chart
|
||||
|
||||
[](https://artifacthub.io/packages/helm/weknora/weknora)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
Helm chart for deploying [WeKnora](https://github.com/Tencent/WeKnora) - an AI-powered Knowledge RAG Platform.
|
||||
|
||||
## Overview
|
||||
|
||||
WeKnora is an intelligent knowledge base platform that combines:
|
||||
- Document parsing and understanding
|
||||
- Vector search with BM25 hybrid retrieval
|
||||
- LLM integration for conversational AI
|
||||
- Multi-tenant support with encryption
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.25+
|
||||
- Helm 3.10+
|
||||
- PV provisioner support in the underlying infrastructure
|
||||
- Ingress controller (nginx-ingress recommended) for external access
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Add required secrets
|
||||
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>
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Ingress │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ Frontend │ │ Backend │
|
||||
│ (Vue.js) │ │ (Go/Gin) │
|
||||
└─────────────┘ └──────┬──────┘
|
||||
│
|
||||
┌──────────────────────┼──────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Docreader │ │ PostgreSQL │ │ Redis │
|
||||
│ (gRPC) │ │ (ParadeDB) │ │ (Queue) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Basic Installation
|
||||
|
||||
```bash
|
||||
helm install weknora ./helm \
|
||||
--namespace weknora \
|
||||
--create-namespace \
|
||||
--set secrets.dbPassword=secure-password \
|
||||
--set secrets.redisPassword=secure-password \
|
||||
--set secrets.jwtSecret=$(openssl rand -base64 32)
|
||||
```
|
||||
|
||||
### With Ingress
|
||||
|
||||
```bash
|
||||
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)
|
||||
```
|
||||
|
||||
### With External LLM (Ollama)
|
||||
|
||||
```bash
|
||||
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)
|
||||
```
|
||||
|
||||
### Production Installation
|
||||
|
||||
For production, use a values file:
|
||||
|
||||
```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 secret
|
||||
```
|
||||
|
||||
```bash
|
||||
helm install weknora ./helm \
|
||||
--namespace weknora \
|
||||
--create-namespace \
|
||||
-f values-production.yaml
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Global Parameters
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `global.storageClass` | Storage class for PVCs | `""` |
|
||||
| `global.imagePullSecrets` | Image pull secrets | `[]` |
|
||||
| `global.podSecurityContext` | Pod security context | See values.yaml |
|
||||
| `global.containerSecurityContext` | Container security context | See values.yaml |
|
||||
|
||||
### ServiceAccount
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `serviceAccount.create` | Create ServiceAccount | `true` |
|
||||
| `serviceAccount.name` | ServiceAccount name | `""` |
|
||||
| `serviceAccount.annotations` | ServiceAccount annotations | `{}` |
|
||||
|
||||
### App (Backend)
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `app.enabled` | Enable backend | `true` |
|
||||
| `app.replicaCount` | Number of replicas | `1` |
|
||||
| `app.image.repository` | Image repository | `wechatopenai/weknora-app` |
|
||||
| `app.image.tag` | Image tag | `""` (uses appVersion) |
|
||||
| `app.resources` | Resource limits | See values.yaml |
|
||||
| `app.env` | Environment variables | See values.yaml |
|
||||
| `app.extraEnv` | Additional env vars | `[]` |
|
||||
|
||||
### Frontend
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `frontend.enabled` | Enable frontend | `true` |
|
||||
| `frontend.replicaCount` | Number of replicas | `1` |
|
||||
| `frontend.image.repository` | Image repository | `wechatopenai/weknora-ui` |
|
||||
| `frontend.image.tag` | Image tag | `latest` |
|
||||
|
||||
### PostgreSQL (ParadeDB)
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `postgresql.enabled` | Enable PostgreSQL | `true` |
|
||||
| `postgresql.image.repository` | Image repository | `paradedb/paradedb` |
|
||||
| `postgresql.image.tag` | Image tag | `v0.18.9-pg17` |
|
||||
| `postgresql.persistence.enabled` | Enable persistence | `true` |
|
||||
| `postgresql.persistence.size` | PVC size | `10Gi` |
|
||||
|
||||
### Redis
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `redis.enabled` | Enable Redis | `true` |
|
||||
| `redis.image.repository` | Image repository | `redis` |
|
||||
| `redis.image.tag` | Image tag | `7-alpine` |
|
||||
| `redis.persistence.enabled` | Enable persistence | `true` |
|
||||
| `redis.persistence.size` | PVC size | `1Gi` |
|
||||
|
||||
### Ingress
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `ingress.enabled` | Enable ingress | `false` |
|
||||
| `ingress.className` | Ingress class | `nginx` |
|
||||
| `ingress.host` | Hostname | `weknora.example.com` |
|
||||
| `ingress.tls.enabled` | Enable TLS | `false` |
|
||||
| `ingress.tls.secretName` | TLS secret name | `""` |
|
||||
|
||||
### Secrets
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `secrets.dbUser` | Database username | `postgres` |
|
||||
| `secrets.dbPassword` | Database password | `""` (required) |
|
||||
| `secrets.dbName` | Database name | `weknora` |
|
||||
| `secrets.redisPassword` | Redis password | `""` (required) |
|
||||
| `secrets.jwtSecret` | JWT signing secret | `""` (required) |
|
||||
| `secrets.existingSecret` | Use existing secret | `""` |
|
||||
|
||||
### Optional Components
|
||||
|
||||
These map to docker-compose profiles:
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `minio.enabled` | Enable MinIO storage | `false` |
|
||||
| `neo4j.enabled` | Enable Neo4j (GraphRAG) | `false` |
|
||||
| `qdrant.enabled` | Enable Qdrant vector DB | `false` |
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Secret Management
|
||||
|
||||
**Never commit secrets to Git!** Use one of these approaches:
|
||||
|
||||
1. **Helm --set flags** (for testing)
|
||||
```bash
|
||||
helm install weknora ./helm --set secrets.dbPassword=xxx
|
||||
```
|
||||
|
||||
2. **External Secrets Operator** (recommended for production)
|
||||
```yaml
|
||||
secrets:
|
||||
existingSecret: weknora-external-secret
|
||||
```
|
||||
|
||||
3. **Sealed Secrets** (for GitOps)
|
||||
```bash
|
||||
kubeseal < secret.yaml > sealed-secret.yaml
|
||||
```
|
||||
|
||||
### Pod Security
|
||||
|
||||
The chart follows CNCF security best practices:
|
||||
- Runs as non-root user
|
||||
- Read-only root filesystem where possible
|
||||
- Drops all capabilities
|
||||
- Uses seccomp profiles
|
||||
|
||||
## Upgrading
|
||||
|
||||
```bash
|
||||
helm upgrade weknora ./helm \
|
||||
--namespace weknora \
|
||||
--reuse-values
|
||||
```
|
||||
|
||||
## Uninstalling
|
||||
|
||||
```bash
|
||||
helm uninstall weknora --namespace weknora
|
||||
|
||||
# Optional: Remove PVCs
|
||||
kubectl delete pvc -n weknora -l app.kubernetes.io/instance=weknora
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Pod Status
|
||||
```bash
|
||||
kubectl get pods -n weknora
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```bash
|
||||
# Backend logs
|
||||
kubectl logs -n weknora -l app.kubernetes.io/component=app -f
|
||||
|
||||
# Frontend logs
|
||||
kubectl logs -n weknora -l app.kubernetes.io/component=frontend -f
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Pod stuck in Pending**
|
||||
- Check if PVCs are bound: `kubectl get pvc -n weknora`
|
||||
- Verify storage class exists: `kubectl get sc`
|
||||
|
||||
**Connection refused errors**
|
||||
- Wait for all pods to be Ready
|
||||
- Check service endpoints: `kubectl get endpoints -n weknora`
|
||||
|
||||
**Database connection errors**
|
||||
- Verify secrets are correct
|
||||
- Check PostgreSQL logs: `kubectl logs -n weknora -l app.kubernetes.io/component=database`
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/Tencent/WeKnora/blob/main/CONTRIBUTING.md) in the main repository.
|
||||
|
||||
## References
|
||||
|
||||
This Helm chart follows best practices from:
|
||||
- [Helm Best Practices](https://helm.sh/docs/chart_best_practices/)
|
||||
- [ArgoCD Helm Chart](https://github.com/argoproj/argo-helm)
|
||||
- [Prometheus Helm Charts](https://github.com/prometheus-community/helm-charts)
|
||||
- [cert-manager Helm Chart](https://github.com/cert-manager/cert-manager)
|
||||
|
||||
## License
|
||||
|
||||
This chart is licensed under the MIT License - see the [LICENSE](https://github.com/Tencent/WeKnora/blob/main/LICENSE) file for details.
|
||||
@@ -0,0 +1,140 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Post-installation notes for WeKnora Helm chart.
|
||||
Ref: https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/templates/NOTES.txt
|
||||
*/}}
|
||||
|
||||
================================================================================
|
||||
WeKnora has been installed successfully!
|
||||
================================================================================
|
||||
|
||||
Release: {{ .Release.Name }}
|
||||
Namespace: {{ .Release.Namespace }}
|
||||
Version: {{ .Chart.AppVersion }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
ACCESSING WEKNORA
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
WeKnora is accessible via Ingress:
|
||||
|
||||
URL: {{ if .Values.ingress.tls.enabled }}https{{ else }}http{{ end }}://{{ .Values.ingress.host }}
|
||||
|
||||
{{- else }}
|
||||
|
||||
To access WeKnora, use port-forwarding:
|
||||
|
||||
# Frontend (Web UI)
|
||||
kubectl port-forward svc/frontend -n {{ .Release.Namespace }} 8080:80
|
||||
|
||||
# Then open: http://localhost:8080
|
||||
|
||||
{{- end }}
|
||||
|
||||
{{- if not .Values.ingress.enabled }}
|
||||
|
||||
To expose WeKnora externally, enable Ingress:
|
||||
|
||||
helm upgrade {{ .Release.Name }} ./helm \
|
||||
--set ingress.enabled=true \
|
||||
--set ingress.host=weknora.example.com
|
||||
|
||||
{{- end }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
CONFIGURATION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Components deployed:
|
||||
{{- if .Values.app.enabled }}
|
||||
- Backend API ({{ include "weknora.app.image" . }})
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.enabled }}
|
||||
- Frontend UI ({{ include "weknora.frontend.image" . }})
|
||||
{{- end }}
|
||||
{{- if .Values.docreader.enabled }}
|
||||
- Document Reader ({{ include "weknora.docreader.image" . }})
|
||||
{{- end }}
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
- PostgreSQL/ParadeDB ({{ include "weknora.postgresql.image" . }})
|
||||
{{- end }}
|
||||
{{- if .Values.redis.enabled }}
|
||||
- Redis ({{ include "weknora.redis.image" . }})
|
||||
{{- end }}
|
||||
|
||||
{{- if or .Values.minio.enabled .Values.neo4j.enabled .Values.qdrant.enabled }}
|
||||
|
||||
Optional components enabled:
|
||||
{{- if .Values.minio.enabled }}
|
||||
- MinIO (S3-compatible storage)
|
||||
{{- end }}
|
||||
{{- if .Values.neo4j.enabled }}
|
||||
- Neo4j (Knowledge Graph)
|
||||
{{- end }}
|
||||
{{- if .Values.qdrant.enabled }}
|
||||
- Qdrant (Vector Database)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
CONNECTING TO LLM
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
WeKnora requires an LLM backend. Configure via environment variables:
|
||||
|
||||
helm upgrade {{ .Release.Name }} ./helm \
|
||||
--set app.extraEnv[0].name=OLLAMA_BASE_URL \
|
||||
--set app.extraEnv[0].value=http://ollama:11434 \
|
||||
--set app.extraEnv[1].name=INIT_LLM_MODEL_NAME \
|
||||
--set app.extraEnv[1].value=qwen2.5:7b
|
||||
|
||||
Supported LLM backends:
|
||||
- Ollama (local)
|
||||
- OpenAI API compatible endpoints
|
||||
- Qwen, DeepSeek, and other Chinese LLMs
|
||||
|
||||
{{- if .Values.neo4j.enabled }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
GRAPHRAG (KNOWLEDGE GRAPH)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Neo4j is enabled for GraphRAG feature.
|
||||
|
||||
To use GraphRAG, enable Neo4j. NEO4J_ENABLE is the sole graph switch and is
|
||||
injected automatically when neo4j.enabled=true (no need to set ENABLE_GRAPH_RAG,
|
||||
which is deprecated and no longer read by the app):
|
||||
|
||||
helm upgrade {{ .Release.Name }} ./helm \
|
||||
--set neo4j.enabled=true \
|
||||
--set neo4j.password=<your-secure-password>
|
||||
|
||||
Access Neo4j Browser:
|
||||
kubectl port-forward svc/neo4j -n {{ .Release.Namespace }} 7474:7474 7687:7687
|
||||
# Open: http://localhost:7474
|
||||
|
||||
{{- end }}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DOCUMENTATION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
GitHub: https://github.com/Tencent/WeKnora
|
||||
API Docs: https://github.com/Tencent/WeKnora/blob/main/docs/api/README.md
|
||||
FAQ: https://github.com/Tencent/WeKnora/blob/main/docs/QA.md
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
TROUBLESHOOTING
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Check pod status:
|
||||
kubectl get pods -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }}
|
||||
|
||||
View logs:
|
||||
kubectl logs -n {{ .Release.Namespace }} -l app.kubernetes.io/component=app -f
|
||||
kubectl logs -n {{ .Release.Namespace }} -l app.kubernetes.io/component=frontend -f
|
||||
|
||||
================================================================================
|
||||
@@ -0,0 +1,195 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
WeKnora Helm Chart Template Helpers
|
||||
|
||||
Best Practices References:
|
||||
- https://helm.sh/docs/chart_best_practices/templates/
|
||||
- https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/templates/_helpers.tpl
|
||||
*/}}
|
||||
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "weknora.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
*/}}
|
||||
{{- define "weknora.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
Ref: https://helm.sh/docs/chart_best_practices/labels/
|
||||
*/}}
|
||||
{{- define "weknora.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels following Kubernetes recommended labels.
|
||||
Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
|
||||
*/}}
|
||||
{{- define "weknora.labels" -}}
|
||||
helm.sh/chart: {{ include "weknora.chart" . }}
|
||||
{{ include "weknora.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.kubernetes.io/part-of: weknora
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "weknora.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "weknora.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Component labels - use for individual components
|
||||
Usage: {{ include "weknora.componentLabels" (dict "component" "app" "context" .) }}
|
||||
*/}}
|
||||
{{- define "weknora.componentLabels" -}}
|
||||
{{ include "weknora.labels" .context }}
|
||||
app.kubernetes.io/component: {{ .component }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Component selector labels
|
||||
Usage: {{ include "weknora.componentSelectorLabels" (dict "component" "app" "context" .) }}
|
||||
*/}}
|
||||
{{- define "weknora.componentSelectorLabels" -}}
|
||||
{{ include "weknora.selectorLabels" .context }}
|
||||
app.kubernetes.io/component: {{ .component }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use.
|
||||
Ref: https://helm.sh/docs/chart_best_practices/rbac/
|
||||
*/}}
|
||||
{{- define "weknora.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "weknora.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Secret name - supports existing secret
|
||||
*/}}
|
||||
{{- define "weknora.secretName" -}}
|
||||
{{- if .Values.secrets.existingSecret }}
|
||||
{{- .Values.secrets.existingSecret }}
|
||||
{{- else }}
|
||||
{{- include "weknora.fullname" . }}-secrets
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the app image with tag.
|
||||
Defaults to Chart.appVersion if tag is not specified.
|
||||
*/}}
|
||||
{{- define "weknora.app.image" -}}
|
||||
{{- $tag := default .Chart.AppVersion .Values.app.image.tag }}
|
||||
{{- printf "%s:%s" .Values.app.image.repository $tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the frontend image with tag.
|
||||
*/}}
|
||||
{{- define "weknora.frontend.image" -}}
|
||||
{{- printf "%s:%s" .Values.frontend.image.repository .Values.frontend.image.tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the docreader image with tag.
|
||||
*/}}
|
||||
{{- define "weknora.docreader.image" -}}
|
||||
{{- printf "%s:%s" .Values.docreader.image.repository .Values.docreader.image.tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the PostgreSQL image with tag.
|
||||
*/}}
|
||||
{{- define "weknora.postgresql.image" -}}
|
||||
{{- printf "%s:%s" .Values.postgresql.image.repository .Values.postgresql.image.tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the Redis image with tag.
|
||||
*/}}
|
||||
{{- define "weknora.redis.image" -}}
|
||||
{{- printf "%s:%s" .Values.redis.image.repository .Values.redis.image.tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the Neo4j image with tag.
|
||||
*/}}
|
||||
{{- define "weknora.neo4j.image" -}}
|
||||
{{- printf "%s:%s" .Values.neo4j.image.repository .Values.neo4j.image.tag }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create image pull secrets list.
|
||||
*/}}
|
||||
{{- define "weknora.imagePullSecrets" -}}
|
||||
{{- with .Values.global.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the storage class name.
|
||||
*/}}
|
||||
{{- define "weknora.storageClass" -}}
|
||||
{{- if .Values.global.storageClass }}
|
||||
{{- if eq .Values.global.storageClass "-" }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: {{ .Values.global.storageClass | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Pod security context.
|
||||
Merges global defaults with component-specific overrides.
|
||||
*/}}
|
||||
{{- define "weknora.podSecurityContext" -}}
|
||||
{{- $global := .Values.global.podSecurityContext | default dict }}
|
||||
{{- $component := .componentSecurityContext | default dict }}
|
||||
{{- $merged := merge $component $global }}
|
||||
{{- if $merged }}
|
||||
securityContext:
|
||||
{{- toYaml $merged | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Container security context.
|
||||
*/}}
|
||||
{{- define "weknora.containerSecurityContext" -}}
|
||||
{{- if . }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,201 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
WeKnora Backend API Server Deployment and Service.
|
||||
*/}}
|
||||
{{- if .Values.app.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-app
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "app" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.app.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "app" "context" .) | nindent 6 }}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "app" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.app.podSecurityContext | default .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: app
|
||||
image: {{ include "weknora.app.image" . }}
|
||||
imagePullPolicy: {{ .Values.app.image.pullPolicy }}
|
||||
{{- with .Values.app.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
env:
|
||||
# Application settings
|
||||
- name: GIN_MODE
|
||||
value: {{ .Values.app.env.GIN_MODE | quote }}
|
||||
- name: TZ
|
||||
value: {{ .Values.app.env.TZ | quote }}
|
||||
# Database configuration
|
||||
- name: DB_DRIVER
|
||||
value: "postgres"
|
||||
- name: DB_HOST
|
||||
value: "postgres"
|
||||
- name: DB_PORT
|
||||
value: "5432"
|
||||
- name: DB_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_USER
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_PASSWORD
|
||||
- name: DB_NAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_NAME
|
||||
# Redis configuration
|
||||
- name: REDIS_ADDR
|
||||
value: "redis:6379"
|
||||
- name: REDIS_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: REDIS_USERNAME
|
||||
optional: true
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: REDIS_PASSWORD
|
||||
- name: REDIS_DB
|
||||
value: "0"
|
||||
- name: REDIS_PREFIX
|
||||
value: "stream:"
|
||||
- name: STREAM_MANAGER_TYPE
|
||||
value: {{ .Values.app.env.STREAM_MANAGER_TYPE | quote }}
|
||||
# Security
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: JWT_SECRET
|
||||
- name: SYSTEM_AES_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: SYSTEM_AES_KEY
|
||||
# Retrieval & Storage
|
||||
- name: RETRIEVE_DRIVER
|
||||
value: {{ .Values.app.env.RETRIEVE_DRIVER | quote }}
|
||||
- name: STORAGE_TYPE
|
||||
value: {{ .Values.app.env.STORAGE_TYPE | quote }}
|
||||
- name: LOCAL_STORAGE_BASE_DIR
|
||||
value: {{ .Values.app.env.LOCAL_STORAGE_BASE_DIR | quote }}
|
||||
# Document reader
|
||||
- name: DOCREADER_ADDR
|
||||
value: "docreader:50051"
|
||||
# Processing
|
||||
- name: AUTO_RECOVER_DIRTY
|
||||
value: {{ .Values.app.env.AUTO_RECOVER_DIRTY | quote }}
|
||||
- name: CONCURRENCY_POOL_SIZE
|
||||
value: {{ .Values.app.env.CONCURRENCY_POOL_SIZE | quote }}
|
||||
# Docker sandbox is off unless the deployer opts in. A workspace
|
||||
# admin who can save a Docker config can create containers on
|
||||
# whatever Engine API this process can reach (often host root).
|
||||
- name: WEKNORA_SANDBOX_DOCKER_ENABLED
|
||||
value: {{ .Values.app.env.WEKNORA_SANDBOX_DOCKER_ENABLED | default "false" | quote }}
|
||||
{{- if .Values.neo4j.enabled }}
|
||||
# Neo4j configuration (for GraphRAG)
|
||||
# NEO4J_ENABLE 是知识图谱的唯一开关(Go 代码认它,不认 ENABLE_GRAPH_RAG)。
|
||||
# neo4j.enabled=true 时自动注入,无需用户单独设置。
|
||||
- name: NEO4J_ENABLE
|
||||
value: "true"
|
||||
- name: NEO4J_URI
|
||||
value: "bolt://neo4j:7687"
|
||||
- name: NEO4J_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: NEO4J_USERNAME
|
||||
- name: NEO4J_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: NEO4J_PASSWORD
|
||||
{{- end }}
|
||||
{{- with .Values.app.extraEnv }}
|
||||
# Additional environment variables
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: data-files
|
||||
mountPath: /data/files
|
||||
resources:
|
||||
{{- toYaml .Values.app.resources | nindent 12 }}
|
||||
{{- with .Values.app.livenessProbe }}
|
||||
livenessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.app.readinessProbe }}
|
||||
readinessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: data-files
|
||||
{{- if .Values.dataFiles.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.dataFiles.persistence.existingClaim | default (printf "%s-data-files" (include "weknora.fullname" .)) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- with .Values.app.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.app.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.app.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "app" - frontend nginx config hardcodes this
|
||||
name: app
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "app" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.app.service.type }}
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "app" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.app.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,102 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
WeKnora Document Reader (gRPC) Deployment and Service.
|
||||
*/}}
|
||||
{{- if .Values.docreader.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-docreader
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "docreader" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.docreader.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "docreader" "context" .) | nindent 6 }}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "docreader" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: docreader
|
||||
image: {{ include "weknora.docreader.image" . }}
|
||||
imagePullPolicy: {{ .Values.docreader.image.pullPolicy }}
|
||||
{{- with .Values.docreader.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 50051
|
||||
name: grpc
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: STORAGE_TYPE
|
||||
value: {{ .Values.docreader.env.STORAGE_TYPE | quote }}
|
||||
resources:
|
||||
{{- toYaml .Values.docreader.resources | nindent 12 }}
|
||||
# gRPC health check using grpc_health_probe
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- grpc_health_probe
|
||||
- -addr=localhost:50051
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- grpc_health_probe
|
||||
- -addr=localhost:50051
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
{{- with .Values.docreader.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.docreader.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.docreader.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "docreader" - app references this
|
||||
name: docreader
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "docreader" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.docreader.service.type }}
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "docreader" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: grpc
|
||||
port: {{ .Values.docreader.service.port }}
|
||||
targetPort: grpc
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,112 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
WeKnora Frontend Web UI Deployment and Service.
|
||||
*/}}
|
||||
{{- if .Values.frontend.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-frontend
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "frontend" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.frontend.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "frontend" "context" .) | nindent 6 }}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "frontend" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: frontend
|
||||
image: {{ include "weknora.frontend.image" . }}
|
||||
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
|
||||
{{- with .Values.frontend.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: APP_HOST
|
||||
value: {{ .Values.frontend.appHost | default "app" | quote }}
|
||||
- name: APP_PORT
|
||||
value: {{ .Values.frontend.appPort | default .Values.app.service.port | quote }}
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
resources:
|
||||
{{- toYaml .Values.frontend.resources | nindent 12 }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
# nginx requires writable directories for temp files
|
||||
volumeMounts:
|
||||
- name: nginx-cache
|
||||
mountPath: /var/cache/nginx
|
||||
- name: nginx-run
|
||||
mountPath: /var/run
|
||||
volumes:
|
||||
- name: nginx-cache
|
||||
emptyDir: {}
|
||||
- name: nginx-run
|
||||
emptyDir: {}
|
||||
{{- with .Values.frontend.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.frontend.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "frontend" - ingress references this
|
||||
name: frontend
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "frontend" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.frontend.service.type }}
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "frontend" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.frontend.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,52 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Ingress resource for WeKnora.
|
||||
Routes /api to backend, / to frontend.
|
||||
*/}}
|
||||
{{- if .Values.ingress.enabled }}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "ingress" "context" .) | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.className }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls.enabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
- {{ .Values.ingress.host | quote }}
|
||||
{{- if .Values.ingress.tls.secretName }}
|
||||
secretName: {{ .Values.ingress.tls.secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
- host: {{ .Values.ingress.host | quote }}
|
||||
http:
|
||||
paths:
|
||||
# API routes - must come first (more specific path)
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: app
|
||||
port:
|
||||
name: http
|
||||
# Frontend routes - catch-all
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: frontend
|
||||
port:
|
||||
name: http
|
||||
{{- end }}
|
||||
@@ -0,0 +1,136 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Neo4j Graph Database Deployment and Service.
|
||||
Neo4j is used for GraphRAG feature - knowledge graph storage and querying.
|
||||
Equivalent to: docker compose --profile neo4j
|
||||
*/}}
|
||||
{{- if .Values.neo4j.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-neo4j
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "graph" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "graph" "context" .) | nindent 6 }}
|
||||
# Use Recreate strategy for database to avoid data corruption
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "graph" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: neo4j
|
||||
image: {{ include "weknora.neo4j.image" . }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
{{- with .Values.neo4j.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 7474
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 7687
|
||||
name: bolt
|
||||
protocol: TCP
|
||||
env:
|
||||
# Neo4j 5.0+ requires admin username to be "neo4j"
|
||||
- name: NEO4J_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: NEO4J_PASSWORD
|
||||
- name: NEO4J_AUTH
|
||||
value: "neo4j/$(NEO4J_PASSWORD)"
|
||||
# Disable strict validation to avoid conflict with K8s injected env vars
|
||||
# (K8s injects NEO4J_PORT_* from Service named "neo4j")
|
||||
- name: NEO4J_server_config_strict__validation_enabled
|
||||
value: "false"
|
||||
# APOC plugin configuration
|
||||
- name: NEO4J_apoc_export_file_enabled
|
||||
value: "true"
|
||||
- name: NEO4J_apoc_import_file_enabled
|
||||
value: "true"
|
||||
- name: NEO4J_apoc_import_file_use__neo4j__config
|
||||
value: "true"
|
||||
- name: NEO4J_PLUGINS
|
||||
value: '["apoc"]'
|
||||
volumeMounts:
|
||||
- name: neo4j-data
|
||||
mountPath: /data
|
||||
resources:
|
||||
{{- toYaml .Values.neo4j.resources | nindent 12 }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: neo4j-data
|
||||
{{- if .Values.neo4j.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.neo4j.persistence.existingClaim | default (printf "%s-neo4j" (include "weknora.fullname" .)) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- with .Values.neo4j.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.neo4j.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.neo4j.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "neo4j" - app references this
|
||||
name: neo4j
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "graph" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "graph" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: http
|
||||
port: 7474
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
- name: bolt
|
||||
port: 7687
|
||||
targetPort: bolt
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,128 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
PostgreSQL (ParadeDB) Deployment and Service.
|
||||
ParadeDB provides vector search and BM25 full-text search capabilities.
|
||||
*/}}
|
||||
{{- if .Values.postgresql.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-postgres
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "database" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "database" "context" .) | nindent 6 }}
|
||||
# Use Recreate strategy for database to avoid data corruption
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "database" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: postgres
|
||||
image: {{ include "weknora.postgresql.image" . }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
{{- with .Values.postgresql.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
name: postgresql
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_USER
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_PASSWORD
|
||||
- name: POSTGRES_DB
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: DB_NAME
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
volumeMounts:
|
||||
- name: postgres-data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
resources:
|
||||
{{- toYaml .Values.postgresql.resources | nindent 12 }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- postgres
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- postgres
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: postgres-data
|
||||
{{- if .Values.postgresql.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.postgresql.persistence.existingClaim | default (printf "%s-postgres" (include "weknora.fullname" .)) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- with .Values.postgresql.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.postgresql.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.postgresql.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "postgres" - app references this
|
||||
name: postgres
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "database" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "database" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: postgresql
|
||||
port: 5432
|
||||
targetPort: postgresql
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,81 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Persistent Volume Claims for stateful components.
|
||||
*/}}
|
||||
|
||||
{{/* PostgreSQL PVC */}}
|
||||
{{- if and .Values.postgresql.enabled .Values.postgresql.persistence.enabled (not .Values.postgresql.persistence.existingClaim) }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-postgres
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "database" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.postgresql.persistence.size }}
|
||||
{{- include "weknora.storageClass" . | nindent 2 }}
|
||||
---
|
||||
{{- end }}
|
||||
|
||||
{{/* Redis PVC */}}
|
||||
{{- if and .Values.redis.enabled .Values.redis.persistence.enabled (not .Values.redis.persistence.existingClaim) }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-redis
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "cache" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.redis.persistence.size }}
|
||||
{{- include "weknora.storageClass" . | nindent 2 }}
|
||||
---
|
||||
{{- end }}
|
||||
|
||||
{{/* Neo4j PVC */}}
|
||||
{{- if and .Values.neo4j.enabled .Values.neo4j.persistence.enabled (not .Values.neo4j.persistence.existingClaim) }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-neo4j
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "graph" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.neo4j.persistence.size }}
|
||||
{{- include "weknora.storageClass" . | nindent 2 }}
|
||||
---
|
||||
{{- end }}
|
||||
|
||||
{{/* Data Files PVC */}}
|
||||
{{- if and .Values.dataFiles.persistence.enabled (not .Values.dataFiles.persistence.existingClaim) }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-data-files
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "storage" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.dataFiles.persistence.size }}
|
||||
{{- include "weknora.storageClass" . | nindent 2 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,124 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Redis Deployment and Service.
|
||||
Redis is used for stream management and async task queuing.
|
||||
*/}}
|
||||
{{- if .Values.redis.enabled }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "weknora.fullname" . }}-redis
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "cache" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "cache" "context" .) | nindent 6 }}
|
||||
# Use Recreate strategy to avoid data corruption
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "cache" "context" .) | nindent 8 }}
|
||||
spec:
|
||||
{{- include "weknora.imagePullSecrets" . | nindent 6 }}
|
||||
serviceAccountName: {{ include "weknora.serviceAccountName" . }}
|
||||
{{- with .Values.global.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: redis
|
||||
image: {{ include "weknora.redis.image" . }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
{{- with .Values.redis.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- redis-server
|
||||
- --requirepass
|
||||
- $(REDIS_PASSWORD)
|
||||
- --appendonly
|
||||
- "yes"
|
||||
- --dir
|
||||
- /data
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "weknora.secretName" . }}
|
||||
key: REDIS_PASSWORD
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
name: redis
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
resources:
|
||||
{{- toYaml .Values.redis.resources | nindent 12 }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a $REDIS_PASSWORD ping | grep PONG
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a $REDIS_PASSWORD ping | grep PONG
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: redis-data
|
||||
{{- if .Values.redis.persistence.enabled }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.redis.persistence.existingClaim | default (printf "%s-redis" (include "weknora.fullname" .)) }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- with .Values.redis.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.redis.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.redis.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
# Service name must be "redis" - app references this
|
||||
name: redis
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.componentLabels" (dict "component" "cache" "context" .) | nindent 4 }}
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
{{- include "weknora.componentSelectorLabels" (dict "component" "cache" "context" .) | nindent 4 }}
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: redis
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
@@ -0,0 +1,56 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
Secrets for WeKnora components.
|
||||
|
||||
IMPORTANT: For production deployments, use one of these approaches:
|
||||
1. Set values via --set flags during installation
|
||||
2. Use External Secrets Operator with cloud secret managers
|
||||
3. Use sealed-secrets for GitOps workflows
|
||||
4. Provide an existing secret via secrets.existingSecret
|
||||
*/}}
|
||||
{{- if not .Values.secrets.existingSecret }}
|
||||
{{/*
|
||||
Reuse the previously generated random keys on upgrade. Without this lookup,
|
||||
randAlphaNum would re-roll on every `helm upgrade` and rotate SYSTEM_AES_KEY,
|
||||
making any data encrypted with the old key unreadable
|
||||
(e.g. tenants.api_key would surface as enc:v1:... in the UI).
|
||||
*/}}
|
||||
{{- $secretName := include "weknora.secretName" . }}
|
||||
{{- $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) }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ $secretName }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
# Database credentials
|
||||
DB_USER: {{ .Values.secrets.dbUser | quote }}
|
||||
DB_PASSWORD: {{ required "secrets.dbPassword is required" .Values.secrets.dbPassword | quote }}
|
||||
DB_NAME: {{ .Values.secrets.dbName | quote }}
|
||||
# Redis credentials
|
||||
REDIS_USERNAME: {{ .Values.secrets.redisUsername | default "" | quote }}
|
||||
REDIS_PASSWORD: {{ required "secrets.redisPassword is required" .Values.secrets.redisPassword | quote }}
|
||||
# Application secrets
|
||||
JWT_SECRET: {{ required "secrets.jwtSecret is required" .Values.secrets.jwtSecret | quote }}
|
||||
# SYSTEM_AES_KEY 加密:tenants.api_key、模型 API key、向量库凭证、web search provider key、
|
||||
# WeKnoraCloud.AppSecret 等。(TENANT_AES_KEY 已废弃:v0.4.0 起加密统一用 SYSTEM_AES_KEY,
|
||||
# Go 主应用不再读取 TENANT_AES_KEY,已从 Secret 中移除。)
|
||||
SYSTEM_AES_KEY: {{ $systemAesKey | quote }}
|
||||
{{- if .Values.neo4j.enabled }}
|
||||
# Neo4j credentials (for GraphRAG)
|
||||
NEO4J_USERNAME: {{ .Values.neo4j.username | quote }}
|
||||
NEO4J_PASSWORD: {{ required "neo4j.password is required when neo4j is enabled" .Values.neo4j.password | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,24 @@
|
||||
{{/*
|
||||
Copyright 2025 Tencent
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
ServiceAccount for WeKnora components.
|
||||
Ref: https://helm.sh/docs/chart_best_practices/rbac/
|
||||
*/}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "weknora.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "weknora.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.labels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,496 @@
|
||||
# Copyright 2025 Tencent
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# WeKnora Helm Chart Values
|
||||
#
|
||||
# Best Practices References:
|
||||
# - https://helm.sh/docs/chart_best_practices/values/
|
||||
# - https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml
|
||||
# - https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml
|
||||
|
||||
# -- Global configuration shared across all components
|
||||
# @default -- See values.yaml
|
||||
global:
|
||||
# -- Storage class for all PersistentVolumeClaims
|
||||
# Set to "-" to use cluster default, or specify a storage class name
|
||||
storageClass: ""
|
||||
|
||||
# -- Image pull secrets for private registries
|
||||
# @default -- []
|
||||
imagePullSecrets: []
|
||||
# - name: regcred
|
||||
|
||||
# -- Default security context for all pods
|
||||
# Note: Official images (nginx, postgres, redis) run as root by default
|
||||
# Enable runAsNonRoot only if using non-root compatible images
|
||||
# Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
||||
podSecurityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# -- Default security context for all containers
|
||||
# Note: readOnlyRootFilesystem disabled as images require writable filesystem
|
||||
containerSecurityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- ServiceAccount configuration
|
||||
# Ref: https://helm.sh/docs/chart_best_practices/rbac/
|
||||
serviceAccount:
|
||||
# -- Create a ServiceAccount
|
||||
create: true
|
||||
# -- ServiceAccount name (auto-generated if empty)
|
||||
name: ""
|
||||
# -- Annotations to add to the ServiceAccount
|
||||
annotations: {}
|
||||
# -- Labels to add to the ServiceAccount
|
||||
labels: {}
|
||||
# -- Automount API credentials for the ServiceAccount
|
||||
automountServiceAccountToken: false
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# App (Backend API Server)
|
||||
# -----------------------------------------------------------------------------
|
||||
app:
|
||||
# -- Enable the app component
|
||||
enabled: true
|
||||
|
||||
# -- Number of replicas
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
# -- Image repository
|
||||
repository: wechatopenai/weknora-app
|
||||
# -- Image tag (defaults to Chart.appVersion if empty)
|
||||
tag: ""
|
||||
# -- Image pull policy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# -- Resource requests and limits
|
||||
# Ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1Gi
|
||||
|
||||
# -- Pod security context override
|
||||
podSecurityContext: {}
|
||||
|
||||
# -- Container security context override
|
||||
# Note: App requires write access for file storage
|
||||
securityContext:
|
||||
# runAsNonRoot: true # Disabled - official images run as root
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Environment variables for the app container
|
||||
# Ref: https://github.com/Tencent/WeKnora/blob/main/docker-compose.yml
|
||||
env:
|
||||
GIN_MODE: release
|
||||
# -- Retrieval driver: postgres, elasticsearch_v7, elasticsearch_v8, qdrant
|
||||
RETRIEVE_DRIVER: postgres
|
||||
# -- Storage type: local, minio, cos, tos, s3
|
||||
STORAGE_TYPE: local
|
||||
LOCAL_STORAGE_BASE_DIR: /data/files
|
||||
AUTO_RECOVER_DIRTY: "true"
|
||||
STREAM_MANAGER_TYPE: redis
|
||||
CONCURRENCY_POOL_SIZE: "5"
|
||||
TZ: UTC
|
||||
# Docker sandbox talks to a local Engine API (often docker.sock = host root).
|
||||
# Leave false unless this is a private single-node install that also mounts
|
||||
# the daemon socket or points at a remote tcp:// daemon with TLS.
|
||||
WEKNORA_SANDBOX_DOCKER_ENABLED: "false"
|
||||
|
||||
# -- Additional environment variables
|
||||
extraEnv: []
|
||||
# - name: OLLAMA_BASE_URL
|
||||
# value: "http://ollama:11434"
|
||||
|
||||
# -- Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8080
|
||||
|
||||
# -- Liveness probe configuration
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
|
||||
# -- Readiness probe configuration
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Frontend (Web UI)
|
||||
# -----------------------------------------------------------------------------
|
||||
frontend:
|
||||
# -- Enable the frontend component
|
||||
enabled: true
|
||||
|
||||
# -- Number of replicas
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
# -- Image repository
|
||||
repository: wechatopenai/weknora-ui
|
||||
# -- Image tag
|
||||
tag: latest
|
||||
# -- Image pull policy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# -- Resource requests and limits
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
|
||||
# -- Container security context
|
||||
securityContext:
|
||||
# runAsNonRoot: true # Disabled - official images run as root
|
||||
# readOnlyRootFilesystem: true # Disabled - images require writable fs
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Docreader (Document Parser - gRPC)
|
||||
# -----------------------------------------------------------------------------
|
||||
docreader:
|
||||
# -- Enable the docreader component
|
||||
enabled: true
|
||||
|
||||
# -- Number of replicas
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
# -- Image repository
|
||||
repository: wechatopenai/weknora-docreader
|
||||
# -- Image tag
|
||||
tag: latest
|
||||
# -- Image pull policy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# -- Resource requests and limits
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
|
||||
# -- Container security context
|
||||
securityContext:
|
||||
# runAsNonRoot: true # Disabled - official images run as root
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Environment variables
|
||||
env:
|
||||
STORAGE_TYPE: local
|
||||
|
||||
# -- Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 50051
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# PostgreSQL (ParadeDB - Vector + BM25 Search)
|
||||
# -----------------------------------------------------------------------------
|
||||
postgresql:
|
||||
# -- Enable PostgreSQL
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
# -- Image repository (ParadeDB for vector search)
|
||||
repository: paradedb/paradedb
|
||||
# -- Image tag
|
||||
tag: v0.18.9-pg17
|
||||
|
||||
# -- Resource requests and limits
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
|
||||
# -- Container security context
|
||||
# Note: PostgreSQL requires specific user permissions
|
||||
securityContext:
|
||||
# runAsNonRoot: true # Disabled - official images run as root
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Persistence configuration
|
||||
persistence:
|
||||
# -- Enable persistence
|
||||
enabled: true
|
||||
# -- Size of the PVC
|
||||
size: 10Gi
|
||||
# -- Use existing PVC (leave empty to create new)
|
||||
existingClaim: ""
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Redis (Stream & Task Queue)
|
||||
# -----------------------------------------------------------------------------
|
||||
redis:
|
||||
# -- Enable Redis
|
||||
enabled: true
|
||||
|
||||
image:
|
||||
# -- Image repository
|
||||
repository: redis
|
||||
# -- Image tag
|
||||
tag: 7-alpine
|
||||
|
||||
# -- Resource requests and limits
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
|
||||
# -- Container security context
|
||||
securityContext:
|
||||
# runAsNonRoot: true # Disabled - official images run as root
|
||||
# readOnlyRootFilesystem: true # Disabled - images require writable fs
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Persistence configuration
|
||||
persistence:
|
||||
# -- Enable persistence
|
||||
enabled: true
|
||||
# -- Size of the PVC
|
||||
size: 1Gi
|
||||
# -- Use existing PVC (leave empty to create new)
|
||||
existingClaim: ""
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Data Files Storage
|
||||
# -----------------------------------------------------------------------------
|
||||
dataFiles:
|
||||
persistence:
|
||||
# -- Enable persistence for uploaded files
|
||||
enabled: true
|
||||
# -- Size of the PVC
|
||||
size: 10Gi
|
||||
# -- Use existing PVC (leave empty to create new)
|
||||
existingClaim: ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Ingress Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
ingress:
|
||||
# -- Enable ingress
|
||||
enabled: false
|
||||
|
||||
# -- Ingress class name
|
||||
className: nginx
|
||||
|
||||
# -- Ingress hostname
|
||||
host: weknora.example.com
|
||||
|
||||
# -- TLS configuration
|
||||
tls:
|
||||
# -- Enable TLS
|
||||
enabled: false
|
||||
# -- TLS secret name
|
||||
secretName: ""
|
||||
|
||||
# -- Additional annotations
|
||||
# Ref: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/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"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Secrets Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
# IMPORTANT: Do NOT use default values in production!
|
||||
# Use --set or external secret management (External Secrets Operator, Vault, etc.)
|
||||
#
|
||||
# Example installation:
|
||||
# helm install weknora ./helm \
|
||||
# --set secrets.dbPassword=<secure-password> \
|
||||
# --set secrets.redisPassword=<secure-password> \
|
||||
# --set secrets.jwtSecret=<secure-random-string>
|
||||
#
|
||||
secrets:
|
||||
# -- Database username
|
||||
dbUser: postgres
|
||||
# -- Database password (REQUIRED: change in production)
|
||||
dbPassword: ""
|
||||
# -- Database name
|
||||
dbName: weknora
|
||||
# -- Redis username (OPTIONAL: for Redis 6.0+ ACL)
|
||||
redisUsername: ""
|
||||
# -- Redis password (REQUIRED: change in production)
|
||||
redisPassword: ""
|
||||
# -- JWT signing secret (REQUIRED: change in production)
|
||||
jwtSecret: ""
|
||||
# -- System AES-256 key for database field encryption (must be exactly 32 bytes).
|
||||
# Encrypts: tenants.api_key, model API keys, vector store credentials,
|
||||
# web search provider keys, WeKnoraCloud.AppSecret.
|
||||
# STRONGLY RECOMMENDED to set this explicitly in production. If left empty, a
|
||||
# random 32-char value is generated on first install and reused on subsequent
|
||||
# `helm upgrade` via Secret lookup. However, if the Secret is ever
|
||||
# deleted/recreated (e.g. namespace recreated, GitOps prune, cluster rebuilt)
|
||||
# a new random value will be generated and any data encrypted with the old
|
||||
# key becomes UNRECOVERABLE (the UI will display ciphertext like "enc:v1:..."
|
||||
# instead of plaintext).
|
||||
# NOTE: TENANT_AES_KEY is deprecated since v0.4.0 — encryption now uses
|
||||
# SYSTEM_AES_KEY exclusively. The Go app no longer reads TENANT_AES_KEY and
|
||||
# it has been removed from the Secret.
|
||||
systemAesKey: ""
|
||||
|
||||
# -- Use existing secret instead of creating one
|
||||
# The secret must contain keys: DB_USER, DB_PASSWORD, DB_NAME, REDIS_USERNAME, REDIS_PASSWORD, JWT_SECRET, SYSTEM_AES_KEY
|
||||
existingSecret: ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Optional Components (Profiles from docker-compose)
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# -- MinIO configuration (S3-compatible storage)
|
||||
# Equivalent to: docker compose --profile minio
|
||||
minio:
|
||||
# -- Enable MinIO
|
||||
enabled: false
|
||||
image:
|
||||
repository: minio/minio
|
||||
tag: latest
|
||||
# -- Root user
|
||||
rootUser: minioadmin
|
||||
# -- Root password (REQUIRED if enabled)
|
||||
rootPassword: ""
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 20Gi
|
||||
|
||||
# -- Neo4j configuration (Knowledge Graph)
|
||||
# Equivalent to: docker compose --profile neo4j
|
||||
# Required for GraphRAG feature (sets NEO4J_ENABLE=true automatically when enabled)
|
||||
neo4j:
|
||||
# -- Enable Neo4j for GraphRAG
|
||||
enabled: false
|
||||
|
||||
image:
|
||||
# -- Image repository
|
||||
repository: neo4j
|
||||
# -- Image tag (matches docker-compose.yml)
|
||||
tag: "2025.10.1"
|
||||
|
||||
# -- Neo4j authentication username
|
||||
username: neo4j
|
||||
# -- Neo4j authentication password (REQUIRED if enabled)
|
||||
password: ""
|
||||
|
||||
# -- Resource requests and limits
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 2Gi
|
||||
|
||||
# -- Container security context
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
||||
# -- Persistence configuration
|
||||
persistence:
|
||||
# -- Enable persistence
|
||||
enabled: true
|
||||
# -- Size of the PVC
|
||||
size: 10Gi
|
||||
# -- Use existing PVC (leave empty to create new)
|
||||
existingClaim: ""
|
||||
|
||||
# -- Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Tolerations
|
||||
tolerations: []
|
||||
|
||||
# -- Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# -- Qdrant configuration (Vector Database)
|
||||
# Equivalent to: docker compose --profile qdrant
|
||||
qdrant:
|
||||
# -- Enable Qdrant as alternative vector store
|
||||
enabled: false
|
||||
image:
|
||||
repository: qdrant/qdrant
|
||||
tag: latest
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
Reference in New Issue
Block a user