From 39969c78b9f255e13d276105310b0a37a2616a6d Mon Sep 17 00:00:00 2001 From: Dmitry Shmulevich Date: Wed, 10 Jun 2026 14:25:40 -0700 Subject: [PATCH] feat(helm): add node-data-broker ConfigMap mounts Signed-off-by: Dmitry Shmulevich --- .../node-data-broker/templates/_helpers.tpl | 17 ++++++++++ .../templates/configmap-mounts.yaml | 17 ++++++++++ .../node-data-broker/templates/daemonset.yaml | 34 +++++++++++++++++-- .../charts/node-data-broker/values.yaml | 13 +++++++ charts/topograph/values.k8s.ib-example.yaml | 18 ++++------ docs/providers/infiniband.md | 14 ++++++++ scripts/chart-test.sh | 9 +++++ .../values.k8s.ib-example.yaml.golden.yaml | 24 +++++-------- 8 files changed, 115 insertions(+), 31 deletions(-) create mode 100644 charts/topograph/charts/node-data-broker/templates/configmap-mounts.yaml diff --git a/charts/topograph/charts/node-data-broker/templates/_helpers.tpl b/charts/topograph/charts/node-data-broker/templates/_helpers.tpl index 25bee40e..f0762bb6 100644 --- a/charts/topograph/charts/node-data-broker/templates/_helpers.tpl +++ b/charts/topograph/charts/node-data-broker/templates/_helpers.tpl @@ -60,3 +60,20 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Create the name of a generated ConfigMap mount. +*/}} +{{- define "node-data-broker.configMapMountName" -}} +{{- $root := .root -}} +{{- $name := required "node-data-broker.configMapMounts[].name is required" .name | lower | replace "_" "-" -}} +{{- printf "%s-%s" (include "node-data-broker.fullname" $root) $name | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the volume name for a generated ConfigMap mount. +*/}} +{{- define "node-data-broker.configMapMountVolumeName" -}} +{{- $name := required "node-data-broker.configMapMounts[].name is required" .name | lower | replace "_" "-" -}} +{{- printf "config-map-%s" $name | trunc 63 | trimSuffix "-" }} +{{- end }} diff --git a/charts/topograph/charts/node-data-broker/templates/configmap-mounts.yaml b/charts/topograph/charts/node-data-broker/templates/configmap-mounts.yaml new file mode 100644 index 00000000..a196b315 --- /dev/null +++ b/charts/topograph/charts/node-data-broker/templates/configmap-mounts.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.enabled .Values.configMapMounts }} +{{- range .Values.configMapMounts }} +{{- $data := required "node-data-broker.configMapMounts[].data is required" .data }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-data-broker.configMapMountName" (dict "root" $ "name" .name) }} + labels: + {{- include "node-data-broker.labels" $ | nindent 4 }} +data: + {{- range $key, $value := $data }} + {{ $key | quote }}: |- +{{ default "" $value | indent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/topograph/charts/node-data-broker/templates/daemonset.yaml b/charts/topograph/charts/node-data-broker/templates/daemonset.yaml index 2fc37fab..3734e350 100644 --- a/charts/topograph/charts/node-data-broker/templates/daemonset.yaml +++ b/charts/topograph/charts/node-data-broker/templates/daemonset.yaml @@ -1,6 +1,7 @@ {{- if .Values.enabled }} {{- $providerParams := default dict .Values.global.provider.params }} {{- $useGpuCliqueLabel := and (eq .Values.global.provider.name "infiniband-k8s") (eq (lower (toString (get $providerParams "useGpuCliqueLabel"))) "true") }} +{{- $configMapMounts := default list .Values.configMapMounts }} apiVersion: apps/v1 kind: DaemonSet metadata: @@ -44,9 +45,19 @@ spec: valueFrom: fieldRef: fieldPath: spec.nodeName - {{- with .Values.volumeMounts }} + {{- if or $configMapMounts .Values.volumeMounts }} volumeMounts: + {{- range $configMapMounts }} + - name: {{ include "node-data-broker.configMapMountVolumeName" (dict "name" .name) }} + mountPath: {{ required "node-data-broker.configMapMounts[].mountPath is required" .mountPath | quote }} + {{- with .subPath }} + subPath: {{ . | quote }} + {{- end }} + readOnly: true + {{- end }} + {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} + {{- end }} {{- end }} {{- end }} containers: @@ -61,13 +72,30 @@ spec: {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.volumeMounts }} + {{- if or $configMapMounts .Values.volumeMounts }} volumeMounts: + {{- range $configMapMounts }} + - name: {{ include "node-data-broker.configMapMountVolumeName" (dict "name" .name) }} + mountPath: {{ required "node-data-broker.configMapMounts[].mountPath is required" .mountPath | quote }} + {{- with .subPath }} + subPath: {{ . | quote }} + {{- end }} + readOnly: true + {{- end }} + {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} + {{- end }} {{- end }} - {{- with .Values.volumes }} + {{- if or $configMapMounts .Values.volumes }} volumes: + {{- range $configMapMounts }} + - name: {{ include "node-data-broker.configMapMountVolumeName" (dict "name" .name) }} + configMap: + name: {{ include "node-data-broker.configMapMountName" (dict "root" $ "name" .name) }} + {{- end }} + {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: diff --git a/charts/topograph/charts/node-data-broker/values.yaml b/charts/topograph/charts/node-data-broker/values.yaml index 239313d2..c11e01ab 100644 --- a/charts/topograph/charts/node-data-broker/values.yaml +++ b/charts/topograph/charts/node-data-broker/values.yaml @@ -62,6 +62,19 @@ resources: cpu: 100m memory: 128Mi +# Optional ConfigMaps rendered by the chart and mounted into both the +# node-data-broker container and init container. Set subPath for file mounts; +# omit it to mount the whole ConfigMap as a directory. +configMapMounts: [] +# name is used as a Kubernetes resource and volume suffix; keep it DNS-label-safe. +# - name: ibdiag +# mountPath: /etc/infiniband-diags/ibdiag.conf +# subPath: ibdiag.conf +# data: +# ibdiag.conf: |- +# CA=smi0 +# Port=1 + # Additional volumes on the output Deployment definition. volumes: [] # - name: foo diff --git a/charts/topograph/values.k8s.ib-example.yaml b/charts/topograph/values.k8s.ib-example.yaml index 164d2cfd..c9eff711 100644 --- a/charts/topograph/values.k8s.ib-example.yaml +++ b/charts/topograph/values.k8s.ib-example.yaml @@ -1,10 +1,8 @@ -# Default values for topology-generator. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - global: provider: name: infiniband-k8s + params: + useGpuCliqueLabel: true engine: name: k8s @@ -12,26 +10,22 @@ node-observer: topograph: trigger: nodeSelector: - brightcomputing.com/node-category: dgx + nvidia.com/gpu.present: "true" node-data-broker: image: repository: ghcr.io/nvidia/topograph/ib pullPolicy: IfNotPresent tag: main - initc: - extraArgs: - - gpu-operator-namespace=gpu-operator - - device-plugin-daemonset=nvidia-device-plugin-daemonset securityContext: privileged: true nodeSelector: - brightcomputing.com/node-category: dgx + nvidia.com/gpu.present: "true" volumeMounts: - - name: sys-class + - name: sys-class-volume mountPath: /sys/class volumes: - - name: sys-class + - name: sys-class-volume hostPath: path: /sys/class type: Directory diff --git a/docs/providers/infiniband.md b/docs/providers/infiniband.md index 023caeda..16c327ea 100644 --- a/docs/providers/infiniband.md +++ b/docs/providers/infiniband.md @@ -133,6 +133,20 @@ node-data-broker: - device-plugin-daemonset=my-daemonset ``` +If `ibnetdiscover` needs extra config files, the chart can render ConfigMaps and mount them into the node-data-broker pods: + +```yaml +node-data-broker: + configMapMounts: + - name: ibdiag + mountPath: /etc/infiniband-diags/ibdiag.conf + subPath: ibdiag.conf + data: + ibdiag.conf: |- + CA=smi0 + Port=1 +``` + Example request payload with `nodeSelector`: ```json diff --git a/scripts/chart-test.sh b/scripts/chart-test.sh index 14da0cc5..0ed16106 100755 --- a/scripts/chart-test.sh +++ b/scripts/chart-test.sh @@ -247,6 +247,15 @@ echo "== subchart node-data-broker: initc.enabled=false ==" out=$(helm "${helm_common[@]}" --set node-data-broker.initc.enabled=false) assert_output_not_contains "${out}" "init-node-labels" "node-data-broker.initc.enabled=false should omit init container" +echo "== subchart node-data-broker: configMapMounts ==" +out=$(helm "${helm_common[@]}" \ + --set-json 'node-data-broker.configMapMounts=[{"name":"ibdiag","mountPath":"/etc/infiniband-diags/ibdiag.conf","subPath":"ibdiag.conf","data":{"ibdiag.conf":"CA=smi0\nPort=1"}}]') +assert_output_contains "${out}" "name: chart-ci-node-data-broker-ibdiag" "node-data-broker.configMapMounts should render an ibdiag ConfigMap" +assert_output_contains "${out}" " CA=smi0" "node-data-broker configMapMounts should include configured CA" +assert_output_contains "${out}" " Port=1" "node-data-broker configMapMounts should include configured Port" +assert_output_contains "${out}" "mountPath: \"/etc/infiniband-diags/ibdiag.conf\"" "node-data-broker configMapMounts should mount at ibdiag.conf" +assert_output_contains "${out}" "subPath: \"ibdiag.conf\"" "node-data-broker configMapMounts should mount as a single file" + echo "== subchart node-observer: replicaCount override ==" out=$(helm "${helm_common[@]}" --set node-observer.replicaCount=2) assert_output_contains "${out}" "replicas: 2" "node-observer.replicaCount=2 should scale Deployment" diff --git a/tests/charts/values.k8s.ib-example.yaml.golden.yaml b/tests/charts/values.k8s.ib-example.yaml.golden.yaml index b219ff6d..96cb6b23 100644 --- a/tests/charts/values.k8s.ib-example.yaml.golden.yaml +++ b/tests/charts/values.k8s.ib-example.yaml.golden.yaml @@ -54,11 +54,13 @@ data: generateTopologyUrl: "http://chart-ci.topograph.svc.cluster.local:49021/v1/generate" provider: name: infiniband-k8s + params: + useGpuCliqueLabel: true engine: name: k8s trigger: nodeSelector: - brightcomputing.com/node-category: dgx + nvidia.com/gpu.present: "true" --- # Source: topograph/templates/configmap.yml apiVersion: v1 @@ -87,15 +89,6 @@ rules: - apiGroups: [""] resources: [nodes] verbs: [get,list,update] -- apiGroups: [apps] - resources: [daemonsets] - verbs: [get,list] -- apiGroups: [""] - resources: [pods] - verbs: [get,list] -- apiGroups: [""] - resources: [pods/exec] - verbs: [create] --- # Source: topograph/charts/node-observer/templates/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 @@ -230,8 +223,7 @@ spec: args: - --provider=infiniband-k8s - -v=3 - - --set=gpu-operator-namespace=gpu-operator - - --set=device-plugin-daemonset=nvidia-device-plugin-daemonset + - --set=useGpuCliqueLabel=true env: - name: NODE_NAME valueFrom: @@ -239,7 +231,7 @@ spec: fieldPath: spec.nodeName volumeMounts: - mountPath: /sys/class - name: sys-class + name: sys-class-volume containers: - name: node-data-broker securityContext: @@ -260,14 +252,14 @@ spec: memory: 128Mi volumeMounts: - mountPath: /sys/class - name: sys-class + name: sys-class-volume volumes: - hostPath: path: /sys/class type: Directory - name: sys-class + name: sys-class-volume nodeSelector: - brightcomputing.com/node-category: dgx + nvidia.com/gpu.present: "true" --- # Source: topograph/charts/node-observer/templates/deployment.yaml apiVersion: apps/v1