diff --git a/kubernetes/helm/.helmignore b/kubernetes/helm/.helmignore index e69de29bb..e8065247a 100644 --- a/kubernetes/helm/.helmignore +++ b/kubernetes/helm/.helmignore @@ -0,0 +1 @@ +values-minikube.yaml diff --git a/kubernetes/helm/Chart.yaml b/kubernetes/helm/Chart.yaml index c35338c84..ab5b41df6 100644 --- a/kubernetes/helm/Chart.yaml +++ b/kubernetes/helm/Chart.yaml @@ -1,5 +1,21 @@ apiVersion: v2 name: open-webui -description: "Open WebUI: A User-Friendly Web Interface for Chat Interactions 👋" version: 1.0.0 +appVersion: "latest" + +home: https://www.openwebui.com/ icon: https://raw.githubusercontent.com/open-webui/open-webui/main/static/favicon.png + +description: "Open WebUI: A User-Friendly Web Interface for Chat Interactions 👋" +keywords: +- llm +- chat +- web-ui + +sources: +- https://github.com/open-webui/open-webui/tree/main/kubernetes/helm +- https://hub.docker.com/r/ollama/ollama +- https://github.com/open-webui/open-webui/pkgs/container/open-webui + +annotations: + licenses: MIT diff --git a/kubernetes/helm/templates/_helpers.tpl b/kubernetes/helm/templates/_helpers.tpl new file mode 100644 index 000000000..0647a42ae --- /dev/null +++ b/kubernetes/helm/templates/_helpers.tpl @@ -0,0 +1,47 @@ +{{- define "open-webui.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "ollama.name" -}} +ollama +{{- end -}} + +{{- define "ollama.url" -}} +{{- printf "http://%s.%s.svc.cluster.local:%d/api" (include "ollama.name" .) (.Release.Namespace) (.Values.ollama.service.port | int) }} +{{- end }} + +{{- define "chart.name" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{- define "base.labels" -}} +helm.sh/chart: {{ include "chart.name" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{- define "base.selectorLabels" -}} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "open-webui.selectorLabels" -}} +{{ include "base.selectorLabels" . }} +app.kubernetes.io/component: {{ .Chart.Name }} +{{- end }} + +{{- define "open-webui.labels" -}} +{{ include "base.labels" . }} +{{ include "open-webui.selectorLabels" . }} +{{- end }} + +{{- define "ollama.selectorLabels" -}} +{{ include "base.selectorLabels" . }} +app.kubernetes.io/component: {{ include "ollama.name" . }} +{{- end }} + +{{- define "ollama.labels" -}} +{{ include "base.labels" . }} +{{ include "ollama.selectorLabels" . }} +{{- end }} diff --git a/kubernetes/helm/templates/ollama-namespace.yaml b/kubernetes/helm/templates/ollama-namespace.yaml deleted file mode 100644 index 59f794477..000000000 --- a/kubernetes/helm/templates/ollama-namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: {{ .Values.namespace }} \ No newline at end of file diff --git a/kubernetes/helm/templates/ollama-service.yaml b/kubernetes/helm/templates/ollama-service.yaml index 54558473a..becb6ad27 100644 --- a/kubernetes/helm/templates/ollama-service.yaml +++ b/kubernetes/helm/templates/ollama-service.yaml @@ -1,13 +1,21 @@ apiVersion: v1 kind: Service metadata: - name: ollama-service - namespace: {{ .Values.namespace }} + name: {{ include "ollama.name" . }} + labels: + {{- include "ollama.labels" . | nindent 4 }} + {{- with .Values.ollama.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: - type: {{ .Values.ollama.service.type }} selector: - app: ollama + {{- include "ollama.selectorLabels" . | nindent 4 }} +{{- with .Values.ollama.service }} + type: {{ .type }} ports: - protocol: TCP - port: {{ .Values.ollama.servicePort }} - targetPort: {{ .Values.ollama.servicePort }} \ No newline at end of file + name: http + port: {{ .port }} + targetPort: http +{{- end }} diff --git a/kubernetes/helm/templates/ollama-statefulset.yaml b/kubernetes/helm/templates/ollama-statefulset.yaml index 83cb6883f..a87aeab09 100644 --- a/kubernetes/helm/templates/ollama-statefulset.yaml +++ b/kubernetes/helm/templates/ollama-statefulset.yaml @@ -1,24 +1,43 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: ollama - namespace: {{ .Values.namespace }} + name: {{ include "ollama.name" . }} + labels: + {{- include "ollama.labels" . | nindent 4 }} + {{- with .Values.ollama.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: - serviceName: "ollama" + serviceName: {{ include "ollama.name" . }} replicas: {{ .Values.ollama.replicaCount }} selector: matchLabels: - app: ollama + {{- include "ollama.selectorLabels" . | nindent 6 }} template: metadata: labels: - app: ollama + {{- include "ollama.labels" . | nindent 8 }} + {{- with .Values.ollama.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} spec: + enableServiceLinks: false + automountServiceAccountToken: false + {{- with .Values.ollama.runtimeClassName }} + runtimeClassName: {{ . }} + {{- end }} containers: - - name: ollama - image: {{ .Values.ollama.image }} + - name: {{ include "ollama.name" . }} + {{- with .Values.ollama.image }} + image: {{ .repository }}:{{ .tag }} + imagePullPolicy: {{ .pullPolicy }} + {{- end }} + tty: true ports: - - containerPort: {{ .Values.ollama.servicePort }} + - name: http + containerPort: {{ .Values.ollama.service.containerPort }} env: {{- if .Values.ollama.gpu.enabled }} - name: PATH @@ -27,29 +46,51 @@ spec: value: /usr/local/nvidia/lib:/usr/local/nvidia/lib64 - name: NVIDIA_DRIVER_CAPABILITIES value: compute,utility - {{- end}} - {{- if .Values.ollama.resources }} - resources: {{- toYaml .Values.ollama.resources | nindent 10 }} + {{- end }} + {{- with .Values.ollama.resources }} + resources: {{- toYaml . | nindent 10 }} {{- end }} volumeMounts: - - name: ollama-volume + - name: data mountPath: /root/.ollama - tty: true {{- with .Values.ollama.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} + {{- with .Values.ollama.tolerations }} tolerations: - {{- if .Values.ollama.gpu.enabled }} - - key: nvidia.com/gpu - operator: Exists - effect: NoSchedule - {{- end }} + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- if and .Values.ollama.persistence.enabled .Values.ollama.persistence.existingClaim }} + - name: data + persistentVolumeClaim: + claimName: {{ .Values.ollama.persistence.existingClaim }} + {{- else if not .Values.ollama.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if and .Values.ollama.persistence.enabled (not .Values.ollama.persistence.existingClaim) }} + [] volumeClaimTemplates: - metadata: - name: ollama-volume + name: data + labels: + {{- include "ollama.selectorLabels" . | nindent 8 }} + {{- with .Values.ollama.persistence.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} spec: - accessModes: [ "ReadWriteOnce" ] + accessModes: + {{- range .Values.ollama.persistence.accessModes }} + - {{ . | quote }} + {{- end }} resources: requests: - storage: {{ .Values.ollama.volumeSize }} \ No newline at end of file + storage: {{ .Values.ollama.persistence.size | quote }} + storageClass: {{ .Values.ollama.persistence.storageClass }} + {{- with .Values.ollama.persistence.selector }} + selector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} diff --git a/kubernetes/helm/templates/webui-deployment.yaml b/kubernetes/helm/templates/webui-deployment.yaml index 08c966886..df13a14b6 100644 --- a/kubernetes/helm/templates/webui-deployment.yaml +++ b/kubernetes/helm/templates/webui-deployment.yaml @@ -1,38 +1,62 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: open-webui-deployment - namespace: {{ .Values.namespace }} + name: {{ include "open-webui.name" . }} + labels: + {{- include "open-webui.labels" . | nindent 4 }} + {{- with .Values.webui.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: - replicas: 1 + replicas: {{ .Values.webui.replicaCount }} selector: matchLabels: - app: open-webui + {{- include "open-webui.selectorLabels" . | nindent 6 }} template: metadata: labels: - app: open-webui + {{- include "open-webui.labels" . | nindent 8 }} + {{- with .Values.webui.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} spec: + enableServiceLinks: false + automountServiceAccountToken: false containers: - - name: open-webui - image: {{ .Values.webui.image }} + - name: {{ .Chart.Name }} + {{- with .Values.webui.image }} + image: {{ .repository }}:{{ .tag | default $.Chart.AppVersion }} + imagePullPolicy: {{ .pullPolicy }} + {{- end }} ports: - - containerPort: 8080 - {{- if .Values.webui.resources }} - resources: {{- toYaml .Values.webui.resources | nindent 10 }} + - name: http + containerPort: {{ .Values.webui.service.containerPort }} + {{- with .Values.webui.resources }} + resources: {{- toYaml . | nindent 10 }} {{- end }} volumeMounts: - - name: webui-volume + - name: data mountPath: /app/backend/data env: - name: OLLAMA_API_BASE_URL - value: "http://ollama-service.{{ .Values.namespace }}.svc.cluster.local:{{ .Values.ollama.servicePort }}/api" + value: {{ include "ollama.url" . | quote }} tty: true {{- with .Values.webui.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} volumes: - - name: webui-volume + {{- if and .Values.webui.persistence.enabled .Values.webui.persistence.existingClaim }} + - name: data persistentVolumeClaim: - claimName: open-webui-pvc \ No newline at end of file + claimName: {{ .Values.webui.persistence.existingClaim }} + {{- else if not .Values.webui.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if and .Values.webui.persistence.enabled (not .Values.webui.persistence.existingClaim) }} + - name: data + persistentVolumeClaim: + claimName: {{ include "open-webui.name" . }} + {{- end }} diff --git a/kubernetes/helm/templates/webui-ingress.yaml b/kubernetes/helm/templates/webui-ingress.yaml index cbd456d3f..ea9f95e16 100644 --- a/kubernetes/helm/templates/webui-ingress.yaml +++ b/kubernetes/helm/templates/webui-ingress.yaml @@ -2,13 +2,23 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: open-webui-ingress - namespace: {{ .Values.namespace }} -{{- if .Values.webui.ingress.annotations }} + name: {{ include "open-webui.name" . }} + labels: + {{- include "open-webui.labels" . | nindent 4 }} + {{- with .Values.webui.ingress.annotations }} annotations: -{{ toYaml .Values.webui.ingress.annotations | trimSuffix "\n" | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: + {{- with .Values.webui.ingress.class }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.webui.ingress.tls }} + tls: + - hosts: + - {{ .Values.webui.ingress.host | quote }} + secretName: {{ default (printf "%s-tls" .Release.Name) .Values.webui.ingress.existingSecret }} + {{- end }} rules: - host: {{ .Values.webui.ingress.host }} http: @@ -17,7 +27,7 @@ spec: pathType: Prefix backend: service: - name: open-webui-service + name: {{ include "open-webui.name" . }} port: - number: {{ .Values.webui.servicePort }} + name: http {{- end }} diff --git a/kubernetes/helm/templates/webui-pvc.yaml b/kubernetes/helm/templates/webui-pvc.yaml index d090fe872..06b2cc4a4 100644 --- a/kubernetes/helm/templates/webui-pvc.yaml +++ b/kubernetes/helm/templates/webui-pvc.yaml @@ -1,12 +1,25 @@ +{{- if and .Values.webui.persistence.enabled (not .Values.webui.persistence.existingClaim) }} apiVersion: v1 kind: PersistentVolumeClaim metadata: + name: {{ include "open-webui.name" . }} labels: - app: open-webui - name: open-webui-pvc - namespace: {{ .Values.namespace }} + {{- include "open-webui.selectorLabels" . | nindent 4 }} + {{- with .Values.webui.persistence.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} spec: - accessModes: [ "ReadWriteOnce" ] + accessModes: + {{- range .Values.webui.persistence.accessModes }} + - {{ . | quote }} + {{- end }} resources: requests: - storage: {{ .Values.webui.volumeSize }} \ No newline at end of file + storage: {{ .Values.webui.persistence.size }} + storageClass: {{ .Values.webui.persistence.storageClass }} + {{- with .Values.webui.persistence.selector }} + selector: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/kubernetes/helm/templates/webui-service.yaml b/kubernetes/helm/templates/webui-service.yaml index afd526a15..58da030d3 100644 --- a/kubernetes/helm/templates/webui-service.yaml +++ b/kubernetes/helm/templates/webui-service.yaml @@ -1,15 +1,24 @@ apiVersion: v1 kind: Service metadata: - name: open-webui-service - namespace: {{ .Values.namespace }} + name: {{ include "open-webui.name" . }} + labels: + {{- include "open-webui.labels" . | nindent 4 }} + {{- with .Values.webui.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: - type: {{ .Values.webui.service.type }} # Default: NodePort # Use LoadBalancer if you're on a cloud that supports it selector: - app: open-webui + {{- include "open-webui.selectorLabels" . | nindent 4 }} +{{- with .Values.webui.service }} + type: {{ .type }} ports: - - protocol: TCP - port: {{ .Values.webui.servicePort }} - targetPort: {{ .Values.webui.servicePort }} - # If using NodePort, you can optionally specify the nodePort: - # nodePort: 30000 \ No newline at end of file + - protocol: TCP + name: http + port: {{ .port }} + targetPort: http + {{- if .nodePort }} + nodePort: {{ .nodePort | int }} + {{- end }} +{{- end }} diff --git a/kubernetes/helm/values-minikube.yaml b/kubernetes/helm/values-minikube.yaml new file mode 100644 index 000000000..1b67b0b7c --- /dev/null +++ b/kubernetes/helm/values-minikube.yaml @@ -0,0 +1,27 @@ +ollama: + resources: + requests: + cpu: "2000m" + memory: "2Gi" + limits: + cpu: "4000m" + memory: "4Gi" + nvidia.com/gpu: "0" + service: + type: ClusterIP + gpu: + enabled: false + +webui: + resources: + requests: + cpu: "500m" + memory: "500Mi" + limits: + cpu: "1000m" + memory: "1Gi" + ingress: + enabled: true + host: open-webui.minikube.local + service: + type: NodePort diff --git a/kubernetes/helm/values.yaml b/kubernetes/helm/values.yaml index 63781f6cc..3104dc842 100644 --- a/kubernetes/helm/values.yaml +++ b/kubernetes/helm/values.yaml @@ -1,44 +1,72 @@ -namespace: open-webui +nameOverride: "" ollama: + annotations: {} + podAnnotations: {} replicaCount: 1 - image: ollama/ollama:latest - servicePort: 11434 - resources: - requests: - cpu: "2000m" - memory: "2Gi" - limits: - cpu: "4000m" - memory: "4Gi" - nvidia.com/gpu: "0" - volumeSize: 30Gi + image: + repository: ollama/ollama + tag: latest + pullPolicy: Always + resources: {} + persistence: + enabled: true + size: 30Gi + existingClaim: "" + accessModes: + - ReadWriteOnce + storageClass: "" + selector: {} + annotations: {} + nodeSelector: {} + # -- If using a special runtime container such as nvidia, set it here. + runtimeClassName: "" + tolerations: + - key: nvidia.com/gpu + operator: Exists + effect: NoSchedule + service: + type: ClusterIP + annotations: {} + port: 80 + containerPort: 11434 + gpu: + # -- Enable additional ENV values to help Ollama discover GPU usage + enabled: false + +webui: + annotations: {} + podAnnotations: {} + replicaCount: 1 + image: + repository: ghcr.io/open-webui/open-webui + tag: "" + pullPolicy: Always + resources: {} + ingress: + enabled: false + class: "" + # -- Use appropriate annotations for your Ingress controller, e.g., for NGINX: + # nginx.ingress.kubernetes.io/rewrite-target: / + annotations: {} + host: "" + tls: false + existingSecret: "" + persistence: + enabled: true + size: 2Gi + existingClaim: "" + # -- If using multiple replicas, you must update accessModes to ReadWriteMany + accessModes: + - ReadWriteOnce + storageClass: "" + selector: {} + annotations: {} nodeSelector: {} tolerations: [] service: type: ClusterIP - gpu: - enabled: false - -webui: - replicaCount: 1 - image: ghcr.io/open-webui/open-webui:main - servicePort: 8080 - resources: - requests: - cpu: "500m" - memory: "500Mi" - limits: - cpu: "1000m" - memory: "1Gi" - ingress: - enabled: true - annotations: - # Use appropriate annotations for your Ingress controller, e.g., for NGINX: - # nginx.ingress.kubernetes.io/rewrite-target: / - host: open-webui.minikube.local - volumeSize: 2Gi - nodeSelector: {} - tolerations: [] - service: - type: NodePort \ No newline at end of file + annotations: {} + port: 80 + containerPort: 8080 + nodePort: ""