From 28472572c5d9d0fd6c4696c0b86bb3b972d9cb8b Mon Sep 17 00:00:00 2001 From: Christian Troelsen Date: Mon, 8 Dec 2025 16:14:44 +0000 Subject: [PATCH] add helm support for metrics exporter change fix a few more changes try a fix more fixes add replica count more fixes remove some stuff more changes more changes change change more fixes add helm support for metrics exporter try a fix --- helm/librechat-exporter/Chart.yaml | 29 +++++++ .../librechat-exporter/templates/_helpers.tpl | 62 +++++++++++++ .../templates/deployment.yaml | 83 ++++++++++++++++++ .../librechat-exporter/templates/service.yaml | 17 ++++ .../templates/service_monitor.yaml | 21 +++++ helm/librechat-exporter/values.yaml | 87 +++++++++++++++++++ helm/librechat/Chart.yaml | 4 + helm/librechat/templates/_helpers.tpl | 8 ++ helm/librechat/values.yaml | 41 ++++----- 9 files changed, 329 insertions(+), 23 deletions(-) create mode 100644 helm/librechat-exporter/Chart.yaml create mode 100644 helm/librechat-exporter/templates/_helpers.tpl create mode 100644 helm/librechat-exporter/templates/deployment.yaml create mode 100644 helm/librechat-exporter/templates/service.yaml create mode 100644 helm/librechat-exporter/templates/service_monitor.yaml create mode 100644 helm/librechat-exporter/values.yaml diff --git a/helm/librechat-exporter/Chart.yaml b/helm/librechat-exporter/Chart.yaml new file mode 100644 index 0000000000..ce530948a2 --- /dev/null +++ b/helm/librechat-exporter/Chart.yaml @@ -0,0 +1,29 @@ +apiVersion: v2 +name: librechat-exporter +description: A Prometheus metrics exporter for LibreChat + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed.# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. + +# renovate: image=ghcr.io/virtuos/librechat_exporter:main +appVersion: "2.0.6" + +home: https://www.librechat.ai +sources: + - https://github.com/virtUOS/librechat_exporter diff --git a/helm/librechat-exporter/templates/_helpers.tpl b/helm/librechat-exporter/templates/_helpers.tpl new file mode 100644 index 0000000000..fcb2968748 --- /dev/null +++ b/helm/librechat-exporter/templates/_helpers.tpl @@ -0,0 +1,62 @@ + + + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "librechat-exporter.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} + +{{- define "librechat-exporter.fullname" -}} +{{- if $.Values.fullnameOverride }} +{{- $.Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains .Release.Name $name }} +{{- $name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "librechat-exporter.labels" -}} +helm.sh/chart: {{ include "librechat-exporter.chart" . }} +{{ include "librechat-exporter.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + + +{{/* +Exporter selector labels +*/}} +{{- define "librechat-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "librechat-exporter.fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "librechat-exporter.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "librechat-exporter.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/librechat-exporter/templates/deployment.yaml b/helm/librechat-exporter/templates/deployment.yaml new file mode 100644 index 0000000000..fc271292b7 --- /dev/null +++ b/helm/librechat-exporter/templates/deployment.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "librechat-exporter.fullname" $ }} + labels: + {{- include "librechat-exporter.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "librechat-exporter.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "librechat-exporter.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ include "librechat-exporter.fullname" $ }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.env }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.extraContainers }} + {{ toYaml . | nindent 12 }} + {{- end }} + + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/librechat-exporter/templates/service.yaml b/helm/librechat-exporter/templates/service.yaml new file mode 100644 index 0000000000..e069aad717 --- /dev/null +++ b/helm/librechat-exporter/templates/service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "librechat-exporter.fullname" . }} + labels: + {{- include "librechat-exporter.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "librechat-exporter.selectorLabels" . | nindent 4 }} diff --git a/helm/librechat-exporter/templates/service_monitor.yaml b/helm/librechat-exporter/templates/service_monitor.yaml new file mode 100644 index 0000000000..1488a257ae --- /dev/null +++ b/helm/librechat-exporter/templates/service_monitor.yaml @@ -0,0 +1,21 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "librechat-exporter.fullname" . }} + labels: + {{- include "librechat-exporter.labels" . | nindent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - interval: {{ .Values.serviceMonitor.interval }} + path: /metrics + port: http + scheme: http + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + selector: + matchLabels: + {{- include "librechat-exporter.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/helm/librechat-exporter/values.yaml b/helm/librechat-exporter/values.yaml new file mode 100644 index 0000000000..433b7c653c --- /dev/null +++ b/helm/librechat-exporter/values.yaml @@ -0,0 +1,87 @@ +enabled: false + +replicaCount: 1 + +image: + repository: virtuos/librechat_exporter + registry: ghcr.io + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: main + +env: [] +# - name: MONGODB_URI +# value: "mongodb://mongodb:27017/" +# - name: LOGGING_LEVEL +# value: "info" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: + fsGroup: 2000 + +securityContext: + capabilities: + drop: + - ALL + # readOnlyRootFilesystem: true # not supported yet + runAsNonRoot: true + runAsUser: 1000 + +service: + type: ClusterIP + port: 8000 + annotations: {} + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +extraContainers: {} + +serviceMonitor: + enabled: false + interval: 30s + scrapeTimeout: 30s + labels: [] diff --git a/helm/librechat/Chart.yaml b/helm/librechat/Chart.yaml index cf208fdd60..2084294a1e 100755 --- a/helm/librechat/Chart.yaml +++ b/helm/librechat/Chart.yaml @@ -40,3 +40,7 @@ dependencies: version: "0.5.2" condition: librechat-rag-api.enabled repository: file://../librechat-rag-api + - name: librechat-exporter + version: "0.1.0" + condition: librechat-exporter.enabled + repository: file://../librechat-exporter diff --git a/helm/librechat/templates/_helpers.tpl b/helm/librechat/templates/_helpers.tpl index 4c242d9582..286a329d43 100755 --- a/helm/librechat/templates/_helpers.tpl +++ b/helm/librechat/templates/_helpers.tpl @@ -53,6 +53,14 @@ app.kubernetes.io/name: {{ include "librechat.fullname" . }}-rag app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} +{{/* +Exporter selector labels +*/}} +{{- define "librechat-exporter.selectorLabels" -}} +app.kubernetes.io/name: {{ include "librechat-exporter.fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + {{/* Create the name of the service account to use */}} diff --git a/helm/librechat/values.yaml b/helm/librechat/values.yaml index 169604bfe4..c7fe0f5a2f 100755 --- a/helm/librechat/values.yaml +++ b/helm/librechat/values.yaml @@ -4,17 +4,15 @@ replicaCount: 1 - - global: - # default Secret for envs/ only Passwords. Can be locally generated with: kubectl create secret generic librechat-secret-envs --from-env-file=.env.example --dry-run=client -o yaml > secret-envs.yaml - # For better maintainabillity, you can put all vars directly in the config Section and only overwrite Secrets with this if nessesary. - # Required Values: - # - CREDS_KEY - # - CREDS_IV - # - JWT_SECRET - # - JWT_REFRESH_SECRET - # - MEILI_MASTER_KEY + # default Secret for envs/ only Passwords. Can be locally generated with: kubectl create secret generic librechat-secret-envs --from-env-file=.env.example --dry-run=client -o yaml > secret-envs.yaml + # For better maintainabillity, you can put all vars directly in the config Section and only overwrite Secrets with this if nessesary. + # Required Values: + # - CREDS_KEY + # - CREDS_IV + # - JWT_SECRET + # - JWT_REFRESH_SECRET + # - MEILI_MASTER_KEY librechat: existingSecretName: "librechat-credentials-env" # Used for Setting the Right Key, can be something like AZURE_API_KEY, if Azure OpenAI is used @@ -49,7 +47,7 @@ librechat: # Required Values: # - MEILI_MASTER_KEY existingSecretName: "librechat-credentials-env" - + # For adding a custom config yaml-file you can set the contents in this var. See https://www.librechat.ai/docs/configuration/librechat_yaml/example configYamlContent: "" # configYamlContent: | @@ -69,7 +67,7 @@ librechat: # openNewTab: true # registration: - # socialLogins: ["discord", "facebook", "github", "google", "openid"] + # socialLogins: ["discord", "facebook", "github", "google", "openid"] # endpoints: # azureOpenAI: # # Endpoint-level configuration @@ -110,7 +108,7 @@ librechat: enabled: true size: 10G accessModes: ReadWriteOnce - # storageClassName: + # storageClassName: # only lite RAG is supported librechat-rag-api: @@ -118,6 +116,8 @@ librechat-rag-api: # can be azure, openai, huggingface or huggingfacetei embeddingsProvider: openai +librechat-exporter: + enabled: false image: repository: danny-avila/librechat @@ -126,7 +126,6 @@ image: # Overrides the image tag whose default is the chart appVersion. tag: "" - imagePullSecrets: [] nameOverride: "" fullnameOverride: "" @@ -149,8 +148,6 @@ lifecycle: {} # exec: # command: ["/bin/sh", "-c", "npm run update-banner "] - - podAnnotations: {} podLabels: {} deploymentAnnotations: {} @@ -162,7 +159,7 @@ podSecurityContext: securityContext: capabilities: drop: - - ALL + - ALL # readOnlyRootFilesystem: true # not supported yet runAsNonRoot: true runAsUser: 1000 @@ -202,7 +199,6 @@ resources: {} # cpu: 100m # memory: 128Mi - autoscaling: enabled: false minReplicas: 1 @@ -255,7 +251,7 @@ hostAliases: [] # DNS Configuration # Customize DNS resolution for redirecting traffic to proxy servers -dnsPolicy: "" # Options: ClusterFirst, Default, None, ClusterFirstWithHostNet +dnsPolicy: "" # Options: ClusterFirst, Default, None, ClusterFirstWithHostNet dnsConfig: {} # Example configuration for custom DNS: # dnsPolicy: "None" # Use only custom DNS settings @@ -292,17 +288,16 @@ mongodb: auth: enabled: false databases: - - LibreChat -# persistence: + - LibreChat +# persistence: # size: 8Gi - meilisearch: enabled: true persistence: enabled: true storageClass: "" - image: + image: tag: "v1.7.3" auth: # Use an existing Kubernetes secret for the MEILI_MASTER_KEY