From ea6dcfc5619d56e2a637bf3d28895a7ec8e22bbd Mon Sep 17 00:00:00 2001 From: David Whittington Date: Fri, 24 Jul 2026 10:50:41 -0500 Subject: [PATCH] feat(helm): support custom vm.args via RELEASE_VM_ARGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an opt-in `vmArgs` value rendered into a ConfigMap, mounted at /etc/logflare/vm.args, and wired via RELEASE_VM_ARGS. Defaults to a set including `+Q 1048576`, which caps the BEAM's preallocated port table — needed on Kubernetes, where containerd runs pods with nofile=infinity and the VM would otherwise size the table from that (~2GB RSS at boot). Mounted with subPath so it coexists with the cert-files mount under /etc/logflare. A checksum/vm-args pod annotation rolls the Deployment when the args change. Set vmArgs to "" to fall back to the image's baked-in vm.args. Adds helm-unittest coverage. --- helm/templates/deployment.yaml | 22 ++++++++++- helm/templates/vm-args-configmap.yaml | 11 ++++++ helm/values.yaml | 17 +++++++++ helm/vmargs_test.yaml | 54 +++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 helm/templates/vm-args-configmap.yaml create mode 100644 helm/vmargs_test.yaml diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml index 475cc065ae..340f02e0f6 100644 --- a/helm/templates/deployment.yaml +++ b/helm/templates/deployment.yaml @@ -19,6 +19,9 @@ spec: metadata: annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- if .Values.vmArgs }} + checksum/vm-args: {{ include (print $.Template.BasePath "/vm-args-configmap.yaml") . | sha256sum }} + {{- end }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -75,6 +78,10 @@ spec: - name: LOGFLARE_TLS_KEY_PATH value: {{ printf "%s/cert.key" $mount | quote }} {{- end }} + {{- if .Values.vmArgs }} + - name: RELEASE_VM_ARGS + value: /etc/logflare/vm.args + {{- end }} envFrom: - configMapRef: name: {{ include "logflare.fullname" . }} @@ -98,8 +105,14 @@ spec: resources: {{- toYaml . | nindent 12 }} {{- end }} - {{- if or .Values.logflare.certFilesSecret .Values.volumeMounts }} + {{- if or .Values.vmArgs .Values.logflare.certFilesSecret .Values.volumeMounts }} volumeMounts: + {{- if .Values.vmArgs }} + - name: vm-args + mountPath: /etc/logflare/vm.args + subPath: vm.args + readOnly: true + {{- end }} {{- if .Values.logflare.certFilesSecret }} - name: cert-files mountPath: {{ .Values.logflare.certFilesMountPath }} @@ -109,8 +122,13 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} {{- end }} - {{- if or .Values.logflare.certFilesSecret .Values.volumes }} + {{- if or .Values.vmArgs .Values.logflare.certFilesSecret .Values.volumes }} volumes: + {{- if .Values.vmArgs }} + - name: vm-args + configMap: + name: {{ include "logflare.fullname" . }}-vm-args + {{- end }} {{- if .Values.logflare.certFilesSecret }} - name: cert-files secret: diff --git a/helm/templates/vm-args-configmap.yaml b/helm/templates/vm-args-configmap.yaml new file mode 100644 index 0000000000..2047b30ec3 --- /dev/null +++ b/helm/templates/vm-args-configmap.yaml @@ -0,0 +1,11 @@ +{{- if .Values.vmArgs }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "logflare.fullname" . }}-vm-args + labels: + {{- include "logflare.labels" . | nindent 4 }} +data: + vm.args: | + {{- .Values.vmArgs | nindent 4 }} +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml index 47b6885212..ef54a91c65 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -88,6 +88,23 @@ logflare: postgres: schema: "public" # POSTGRES_BACKEND_SCHEMA; url (POSTGRES_BACKEND_URL) comes from a Secret in logflare.secretRefs +# Erlang VM flags. When set, rendered into a ConfigMap, mounted at +# /etc/logflare/vm.args, and pointed at via RELEASE_VM_ARGS (overriding the +# image's baked-in vm.args). Set to "" to use the image default instead. +# +# `+Q` caps the BEAM's preallocated port table and is effectively REQUIRED on +# Kubernetes: containerd commonly runs pods with nofile=infinity, and without +# +Q the VM sizes the table from that limit — ~2GB RSS at boot. Keep +Q set. +vmArgs: | + +Q 1048576 + +sbwt none + +sbwtdcpu none + +sbwtdio none + +swt very_low + +P 8000000 + -kernel prevent_overlapping_partitions false + -kernel net_ticktime 45 + # This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ imagePullSecrets: [] # This is to override the chart name. diff --git a/helm/vmargs_test.yaml b/helm/vmargs_test.yaml new file mode 100644 index 0000000000..a99b5f31a9 --- /dev/null +++ b/helm/vmargs_test.yaml @@ -0,0 +1,54 @@ +suite: test vm.args wiring +templates: + - vm-args-configmap.yaml + - deployment.yaml +tests: + - it: renders the vm.args ConfigMap with +Q by default + template: vm-args-configmap.yaml + asserts: + - isKind: + of: ConfigMap + - matchRegex: + path: data["vm.args"] + pattern: "\\+Q 1048576" + + - it: sets RELEASE_VM_ARGS and mounts vm-args by default + template: deployment.yaml + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: RELEASE_VM_ARGS + value: /etc/logflare/vm.args + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: vm-args + mountPath: /etc/logflare/vm.args + subPath: vm.args + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: vm-args + configMap: + name: RELEASE-NAME-logflare-vm-args + + - it: renders no ConfigMap when vmArgs is empty + set: + vmArgs: "" + template: vm-args-configmap.yaml + asserts: + - hasDocuments: + count: 0 + + - it: omits RELEASE_VM_ARGS when vmArgs is empty + set: + vmArgs: "" + template: deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: RELEASE_VM_ARGS + value: /etc/logflare/vm.args