diff --git a/helm/.helmignore b/helm/.helmignore index 83b56a95..2e3b5a28 100644 --- a/helm/.helmignore +++ b/helm/.helmignore @@ -1,29 +1,8 @@ -# Patterns to ignore when building packages. .git/ .gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ *.swp *.bak *.tmp *.orig *~ -.project -.idea/ -*.tmproj -.vscode/ .DS_Store -*.md -!README.md -docs/ -tests/ -*_test.yaml -.github/ -.gitlab-ci.yml -.travis.yml -Makefile -values-*.yaml -!values.yaml diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt index e88e2f6f..e9d69cdc 100644 --- a/helm/templates/NOTES.txt +++ b/helm/templates/NOTES.txt @@ -99,6 +99,27 @@ Supported LLM backends: - 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, set ENABLE_GRAPH_RAG=true in the app: + + helm upgrade {{ .Release.Name }} ./helm \ + --set app.env.ENABLE_GRAPH_RAG=true \ + --set neo4j.enabled=true \ + --set neo4j.password= + +Access Neo4j Browser: + kubectl port-forward svc/neo4j -n {{ .Release.Namespace }} 7474:7474 7687:7687 + # Open: http://localhost:7474 + +{{- end }} + -------------------------------------------------------------------------------- DOCUMENTATION -------------------------------------------------------------------------------- diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index 939a7883..c8e75363 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -140,6 +140,13 @@ Return the Redis image with tag. {{- 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. */}} diff --git a/helm/templates/app.yaml b/helm/templates/app.yaml index 0c39a4d3..55aa25b7 100644 --- a/helm/templates/app.yaml +++ b/helm/templates/app.yaml @@ -115,6 +115,21 @@ spec: value: {{ .Values.app.env.CONCURRENCY_POOL_SIZE | quote }} - name: ENABLE_GRAPH_RAG value: {{ .Values.app.env.ENABLE_GRAPH_RAG | quote }} + {{- if .Values.neo4j.enabled }} + # Neo4j configuration (for GraphRAG) + - 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 }} diff --git a/helm/templates/neo4j.yaml b/helm/templates/neo4j.yaml new file mode 100644 index 00000000..935b6769 --- /dev/null +++ b/helm/templates/neo4j.yaml @@ -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 }} diff --git a/helm/templates/pvc.yaml b/helm/templates/pvc.yaml index 99e73669..5d04d735 100644 --- a/helm/templates/pvc.yaml +++ b/helm/templates/pvc.yaml @@ -43,6 +43,25 @@ spec: --- {{- 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 diff --git a/helm/templates/secrets.yaml b/helm/templates/secrets.yaml index a7b89a11..d9503bbb 100644 --- a/helm/templates/secrets.yaml +++ b/helm/templates/secrets.yaml @@ -29,4 +29,9 @@ stringData: # Application secrets JWT_SECRET: {{ required "secrets.jwtSecret is required" .Values.secrets.jwtSecret | quote }} TENANT_AES_KEY: {{ .Values.secrets.tenantAesKey | default (randAlphaNum 32) | 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 }} diff --git a/helm/values.yaml b/helm/values.yaml index 237a9c73..d8bb25c3 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -419,17 +419,52 @@ minio: # -- Neo4j configuration (Knowledge Graph) # Equivalent to: docker compose --profile neo4j +# Required for GraphRAG feature (ENABLE_GRAPH_RAG=true) neo4j: # -- Enable Neo4j for GraphRAG enabled: false + image: + # -- Image repository repository: neo4j - tag: 5-community - # -- Authentication password (REQUIRED if enabled) + # -- 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