From 00e08909468fd7bbab82be21a6dc026da230739e Mon Sep 17 00:00:00 2001 From: root Date: Thu, 23 Apr 2026 11:02:13 +0000 Subject: [PATCH 1/6] refactor: change volumeMounts of statefulset.yaml --- helm/blueapi/README.md | 8 +++++--- helm/blueapi/templates/statefulset.yaml | 3 +++ helm/blueapi/values.schema.json | 18 +----------------- helm/blueapi/values.yaml | 24 ++++++++++-------------- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/helm/blueapi/README.md b/helm/blueapi/README.md index 3862290fb8..cbe0383b57 100644 --- a/helm/blueapi/README.md +++ b/helm/blueapi/README.md @@ -33,7 +33,10 @@ A Helm chart deploying a worker pod that runs Bluesky plans | podLabels | object | `{}` | | | podSecurityContext | object | `{}` | | | readinessProbe | object | `{"failureThreshold":2,"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}` | Readiness probe, if configured kubernetes will not route traffic to this pod if failed consecutively. This could allow the service time to recover if it is being overwhelmed by traffic, but without the to ability to load balance or scale up/outwards, upstream services will need to know to back off. This is automatically disabled when in debug mode. | -| resources | object | `{"limits":{"cpu":"2000m","memory":"4000Mi"},"requests":{"cpu":"200m","memory":"400Mi"}}` | Sets the compute resources available to the pod. These defaults are appropriate when using debug mode or an internal PVC and therefore running VS Code server in the pod. In the Diamond cluster, requests must be >= 0.1*limits When not using either of the above, the limits may be lowered. When idle but connected, blueapi consumes ~400MB of memory and 1% cpu and may struggle when allocated less. | +| resources.limits.cpu | string | `"2000m"` | | +| resources.limits.memory | string | `"4000Mi"` | | +| resources.requests.cpu | string | `"200m"` | | +| resources.requests.memory | string | `"400Mi"` | | | restartOnConfigChange | bool | `true` | If enabled the blueapi pod will restart on changes to `worker` | | securityContext.runAsNonRoot | bool | `true` | | | securityContext.runAsUser | int | `1000` | | @@ -46,11 +49,10 @@ A Helm chart deploying a worker pod that runs Bluesky plans | startupProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}` | A more lenient livenessProbe to allow the service to start fully. This is automatically disabled when in debug mode. | | tolerations | list | `[]` | May be required to run on specific nodes (e.g. the control machine) | | tracing | object | `{"fastapi":{"excludedURLs":"/healthz"},"otlp":{"enabled":false,"protocol":"http/protobuf","server":{"host":"http://opentelemetry-collector.tracing","port":4318}}}` | Exclude health probe requests from tracing by default to prevent spamming | -| volumeMounts | list | `[{"mountPath":"/config","name":"worker-config","readOnly":true}]` | Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name. | +| volumeMounts | string | `nil` | Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name. | | volumes | list | `[]` | Additional volumes on the output StatefulSet definition. Define volumes from e.g. Secrets, ConfigMaps or the Filesystem | | worker | object | `{"api":{"url":"http://0.0.0.0:8000/"},"env":{"sources":[{"kind":"planFunctions","module":"dodal.plans"},{"kind":"planFunctions","module":"dodal.plan_stubs.wrapped"}]},"logging":{"graylog":{"enabled":false,"url":"tcp://graylog-log-target.diamond.ac.uk:12231/"},"level":"INFO"},"scratch":{"repositories":[],"root":"/workspace"},"stomp":{"auth":{"password":"guest","username":"guest"},"enabled":false,"url":"tcp://rabbitmq:61613/"}}` | Config for the worker goes here, will be mounted into a config file | | worker.api.url | string | `"http://0.0.0.0:8000/"` | 0.0.0.0 required to allow non-loopback traffic If using hostNetwork, the port must be free on the host | | worker.env.sources | list | `[{"kind":"planFunctions","module":"dodal.plans"},{"kind":"planFunctions","module":"dodal.plan_stubs.wrapped"}]` | modules (must be installed in the venv) to fetch devices/plans from | -| worker.logging | object | `{"graylog":{"enabled":false,"url":"tcp://graylog-log-target.diamond.ac.uk:12231/"},"level":"INFO"}` | Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` | | worker.scratch | object | `{"repositories":[],"root":"/workspace"}` | If initContainer is enabled the default branch of python projects in this section are installed into the venv *without their dependencies* | | worker.stomp | object | `{"auth":{"password":"guest","username":"guest"},"enabled":false,"url":"tcp://rabbitmq:61613/"}` | Message bus configuration for returning status to GDA/forwarding documents downstream Password may be in the form ${ENV_VAR} to be fetched from an environment variable e.g. mounted from a SealedSecret | diff --git a/helm/blueapi/templates/statefulset.yaml b/helm/blueapi/templates/statefulset.yaml index 36695459b2..556089965e 100644 --- a/helm/blueapi/templates/statefulset.yaml +++ b/helm/blueapi/templates/statefulset.yaml @@ -143,6 +143,9 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} volumeMounts: + - name: worker-config + mountPath: "/config" + readOnly: true {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} diff --git a/helm/blueapi/values.schema.json b/helm/blueapi/values.schema.json index 639209dd90..f53d6157f0 100644 --- a/helm/blueapi/values.schema.json +++ b/helm/blueapi/values.schema.json @@ -198,7 +198,6 @@ } }, "resources": { - "description": "Sets the compute resources available to the pod. These defaults are appropriate when using debug mode or an internal PVC and therefore running VS Code server in the pod. In the Diamond cluster, requests must be \u003e= 0.1*limits When not using either of the above, the limits may be lowered. When idle but connected, blueapi consumes ~400MB of memory and 1% cpu and may struggle when allocated less.", "type": "object", "properties": { "limits": { @@ -334,21 +333,7 @@ }, "volumeMounts": { "description": "Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name.", - "type": "array", - "items": { - "type": "object", - "properties": { - "mountPath": { - "type": "string" - }, - "name": { - "type": "string" - }, - "readOnly": { - "type": "boolean" - } - } - } + "type": "null" }, "volumes": { "description": "Additional volumes on the output StatefulSet definition. Define volumes from e.g. Secrets, ConfigMaps or the Filesystem", @@ -389,7 +374,6 @@ } }, "logging": { - "description": "Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi`", "type": "object", "properties": { "graylog": { diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index 876b37a989..d23fe4a654 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -36,8 +36,7 @@ podAnnotations: {} # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ podLabels: {} -podSecurityContext: {} - # fsGroup: 2000 +podSecurityContext: {} # fsGroup: 2000 securityContext: # https://github.com/DiamondLightSource/blueapi/issues/1096 @@ -48,7 +47,7 @@ securityContext: # drop: # - ALL -# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ + # This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ service: # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types # -- To make blueapi available on an IP outside of the cluster prior to an Ingress being created, change this to LoadBalancer @@ -76,13 +75,13 @@ ingress: # hosts: # - chart-example.local -# -- Sets the compute resources available to the pod. -# These defaults are appropriate when using debug mode or an internal PVC and therefore -# running VS Code server in the pod. -# In the Diamond cluster, requests must be >= 0.1*limits -# When not using either of the above, the limits may be lowered. -# When idle but connected, blueapi consumes ~400MB of memory and 1% cpu -# and may struggle when allocated less. + # -- Sets the compute resources available to the pod. + # These defaults are appropriate when using debug mode or an internal PVC and therefore + # running VS Code server in the pod. + # In the Diamond cluster, requests must be >= 0.1*limits + # When not using either of the above, the limits may be lowered. + # When idle but connected, blueapi consumes ~400MB of memory and 1% cpu + # and may struggle when allocated less. 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 @@ -135,9 +134,6 @@ volumes: [] # -- Additional volumeMounts on the output StatefulSet definition. # Define how volumes are mounted to the container referenced by using the same name. volumeMounts: - - name: worker-config - mountPath: "/config" - readOnly: true # -- May be required to run on specific nodes (e.g. the control machine) nodeSelector: {} @@ -205,7 +201,7 @@ worker: repositories: [] # - name: "dodal" # remote_url: https://github.com/DiamondLightSource/dodal.git - # -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` + # -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` logging: level: "INFO" graylog: From 3627ff633521cc65c7a9e8110829846c3279b457 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 29 Apr 2026 08:21:38 +0000 Subject: [PATCH 2/6] add empty array to volumeMounts --- helm/blueapi/README.md | 2 +- helm/blueapi/values.schema.json | 2 +- helm/blueapi/values.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/helm/blueapi/README.md b/helm/blueapi/README.md index cbe0383b57..566e2f7a39 100644 --- a/helm/blueapi/README.md +++ b/helm/blueapi/README.md @@ -49,7 +49,7 @@ A Helm chart deploying a worker pod that runs Bluesky plans | startupProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}` | A more lenient livenessProbe to allow the service to start fully. This is automatically disabled when in debug mode. | | tolerations | list | `[]` | May be required to run on specific nodes (e.g. the control machine) | | tracing | object | `{"fastapi":{"excludedURLs":"/healthz"},"otlp":{"enabled":false,"protocol":"http/protobuf","server":{"host":"http://opentelemetry-collector.tracing","port":4318}}}` | Exclude health probe requests from tracing by default to prevent spamming | -| volumeMounts | string | `nil` | Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name. | +| volumeMounts | list | `[]` | Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name. | | volumes | list | `[]` | Additional volumes on the output StatefulSet definition. Define volumes from e.g. Secrets, ConfigMaps or the Filesystem | | worker | object | `{"api":{"url":"http://0.0.0.0:8000/"},"env":{"sources":[{"kind":"planFunctions","module":"dodal.plans"},{"kind":"planFunctions","module":"dodal.plan_stubs.wrapped"}]},"logging":{"graylog":{"enabled":false,"url":"tcp://graylog-log-target.diamond.ac.uk:12231/"},"level":"INFO"},"scratch":{"repositories":[],"root":"/workspace"},"stomp":{"auth":{"password":"guest","username":"guest"},"enabled":false,"url":"tcp://rabbitmq:61613/"}}` | Config for the worker goes here, will be mounted into a config file | | worker.api.url | string | `"http://0.0.0.0:8000/"` | 0.0.0.0 required to allow non-loopback traffic If using hostNetwork, the port must be free on the host | diff --git a/helm/blueapi/values.schema.json b/helm/blueapi/values.schema.json index f53d6157f0..df09309f86 100644 --- a/helm/blueapi/values.schema.json +++ b/helm/blueapi/values.schema.json @@ -333,7 +333,7 @@ }, "volumeMounts": { "description": "Additional volumeMounts on the output StatefulSet definition. Define how volumes are mounted to the container referenced by using the same name.", - "type": "null" + "type": "array" }, "volumes": { "description": "Additional volumes on the output StatefulSet definition. Define volumes from e.g. Secrets, ConfigMaps or the Filesystem", diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index d23fe4a654..eeb0947ad1 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -133,7 +133,7 @@ volumes: [] # -- Additional volumeMounts on the output StatefulSet definition. # Define how volumes are mounted to the container referenced by using the same name. -volumeMounts: +volumeMounts: [] # -- May be required to run on specific nodes (e.g. the control machine) nodeSelector: {} From 620aff4c80a9963dc903e915cd985ad137bb5780 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 29 Apr 2026 15:15:29 +0000 Subject: [PATCH 3/6] tests: add expected_mounts to test_volumes_created --- tests/unit_tests/test_helm_chart.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/unit_tests/test_helm_chart.py b/tests/unit_tests/test_helm_chart.py index 43b8b5769a..4c1dcb24b3 100644 --- a/tests/unit_tests/test_helm_chart.py +++ b/tests/unit_tests/test_helm_chart.py @@ -1206,7 +1206,7 @@ def test_service_linked_to_api(worker_api_url: str | None, service_port: int): @pytest.mark.parametrize( "added_mounts", - [[{"name": "worker-config", "mountPath": "/config", "readOnly": True}], [], None], + [[{"name": "foo", "mountPath": "/bar", "readOnly": True}], [], None], ) @pytest.mark.parametrize( "added_volumes", [[{"name": "foo", "configMap": {"name": "bar"}}], [], None] @@ -1218,6 +1218,13 @@ def test_volumes_created( manifests = render_chart( values={"volumes": added_volumes, "volumeMounts": added_mounts} ) + expected_mounts = [ + { + "name": "worker-config", + "mountPath": "/config", + "readOnly": True, + } + ] expected_volumes = [ { @@ -1229,9 +1236,7 @@ def test_volumes_created( if added_volumes: expected_volumes += added_volumes if added_mounts: - expected_mounts = added_mounts - else: - expected_mounts = None + expected_mounts += added_mounts container_mounts = manifests["StatefulSet"]["blueapi"]["spec"]["template"]["spec"][ "containers" From f2305a5656f97eb774baacedc0b5c042f873f076 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 10:06:16 +0000 Subject: [PATCH 4/6] style: unindent few lines in values.yaml --- helm/blueapi/README.md | 5 +---- helm/blueapi/values.schema.json | 1 + helm/blueapi/values.yaml | 18 +++++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/helm/blueapi/README.md b/helm/blueapi/README.md index 566e2f7a39..c8322ef464 100644 --- a/helm/blueapi/README.md +++ b/helm/blueapi/README.md @@ -33,10 +33,7 @@ A Helm chart deploying a worker pod that runs Bluesky plans | podLabels | object | `{}` | | | podSecurityContext | object | `{}` | | | readinessProbe | object | `{"failureThreshold":2,"httpGet":{"path":"/healthz","port":"http"},"periodSeconds":10}` | Readiness probe, if configured kubernetes will not route traffic to this pod if failed consecutively. This could allow the service time to recover if it is being overwhelmed by traffic, but without the to ability to load balance or scale up/outwards, upstream services will need to know to back off. This is automatically disabled when in debug mode. | -| resources.limits.cpu | string | `"2000m"` | | -| resources.limits.memory | string | `"4000Mi"` | | -| resources.requests.cpu | string | `"200m"` | | -| resources.requests.memory | string | `"400Mi"` | | +| resources | object | `{"limits":{"cpu":"2000m","memory":"4000Mi"},"requests":{"cpu":"200m","memory":"400Mi"}}` | Sets the compute resources available to the pod. These defaults are appropriate when using debug mode or an internal PVC and therefore running VS Code server in the pod. In the Diamond cluster, requests must be >= 0.1*limits When not using either of the above, the limits may be lowered. When idle but connected, blueapi consumes ~400MB of memory and 1% cpu and may struggle when allocated less. | | restartOnConfigChange | bool | `true` | If enabled the blueapi pod will restart on changes to `worker` | | securityContext.runAsNonRoot | bool | `true` | | | securityContext.runAsUser | int | `1000` | | diff --git a/helm/blueapi/values.schema.json b/helm/blueapi/values.schema.json index df09309f86..58818f6c92 100644 --- a/helm/blueapi/values.schema.json +++ b/helm/blueapi/values.schema.json @@ -198,6 +198,7 @@ } }, "resources": { + "description": "Sets the compute resources available to the pod. These defaults are appropriate when using debug mode or an internal PVC and therefore running VS Code server in the pod. In the Diamond cluster, requests must be \u003e= 0.1*limits When not using either of the above, the limits may be lowered. When idle but connected, blueapi consumes ~400MB of memory and 1% cpu and may struggle when allocated less.", "type": "object", "properties": { "limits": { diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index eeb0947ad1..370783c3a4 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -47,7 +47,7 @@ securityContext: # drop: # - ALL - # This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ service: # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types # -- To make blueapi available on an IP outside of the cluster prior to an Ingress being created, change this to LoadBalancer @@ -75,13 +75,13 @@ ingress: # hosts: # - chart-example.local - # -- Sets the compute resources available to the pod. - # These defaults are appropriate when using debug mode or an internal PVC and therefore - # running VS Code server in the pod. - # In the Diamond cluster, requests must be >= 0.1*limits - # When not using either of the above, the limits may be lowered. - # When idle but connected, blueapi consumes ~400MB of memory and 1% cpu - # and may struggle when allocated less. +# -- Sets the compute resources available to the pod. +# These defaults are appropriate when using debug mode or an internal PVC and therefore +# running VS Code server in the pod. +# In the Diamond cluster, requests must be >= 0.1*limits +# When not using either of the above, the limits may be lowered. +# When idle but connected, blueapi consumes ~400MB of memory and 1% cpu +# and may struggle when allocated less. 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 @@ -201,7 +201,7 @@ worker: repositories: [] # - name: "dodal" # remote_url: https://github.com/DiamondLightSource/dodal.git - # -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` +# -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` logging: level: "INFO" graylog: From 1b9e68f86f9af71db4163ccbe4b40e719bf1a942 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 10:23:11 +0000 Subject: [PATCH 5/6] add volume and volumeMount example to values.yaml --- helm/blueapi/values.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index 370783c3a4..a83fa74191 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -130,10 +130,18 @@ startupProbe: # -- Additional volumes on the output StatefulSet definition. # Define volumes from e.g. Secrets, ConfigMaps or the Filesystem volumes: [] +# - name: dls-sw-bl +# hostPath: +# path: "/dls_sw/i23" +# type: Directory # -- Additional volumeMounts on the output StatefulSet definition. # Define how volumes are mounted to the container referenced by using the same name. volumeMounts: [] +# - name: dls-sw-bl +# mountPath: /dls_sw/i23 +# readOnly: true +# mountPropagation: HostToContainer # -- May be required to run on specific nodes (e.g. the control machine) nodeSelector: {} From ce196e508b53fa5c94aab93a5a1c657e740a47f5 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Apr 2026 10:46:06 +0000 Subject: [PATCH 6/6] style: indent again --- helm/blueapi/README.md | 1 + helm/blueapi/values.schema.json | 1 + helm/blueapi/values.yaml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/helm/blueapi/README.md b/helm/blueapi/README.md index c8322ef464..4ece387b72 100644 --- a/helm/blueapi/README.md +++ b/helm/blueapi/README.md @@ -51,5 +51,6 @@ A Helm chart deploying a worker pod that runs Bluesky plans | worker | object | `{"api":{"url":"http://0.0.0.0:8000/"},"env":{"sources":[{"kind":"planFunctions","module":"dodal.plans"},{"kind":"planFunctions","module":"dodal.plan_stubs.wrapped"}]},"logging":{"graylog":{"enabled":false,"url":"tcp://graylog-log-target.diamond.ac.uk:12231/"},"level":"INFO"},"scratch":{"repositories":[],"root":"/workspace"},"stomp":{"auth":{"password":"guest","username":"guest"},"enabled":false,"url":"tcp://rabbitmq:61613/"}}` | Config for the worker goes here, will be mounted into a config file | | worker.api.url | string | `"http://0.0.0.0:8000/"` | 0.0.0.0 required to allow non-loopback traffic If using hostNetwork, the port must be free on the host | | worker.env.sources | list | `[{"kind":"planFunctions","module":"dodal.plans"},{"kind":"planFunctions","module":"dodal.plan_stubs.wrapped"}]` | modules (must be installed in the venv) to fetch devices/plans from | +| worker.logging | object | `{"graylog":{"enabled":false,"url":"tcp://graylog-log-target.diamond.ac.uk:12231/"},"level":"INFO"}` | Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` | | worker.scratch | object | `{"repositories":[],"root":"/workspace"}` | If initContainer is enabled the default branch of python projects in this section are installed into the venv *without their dependencies* | | worker.stomp | object | `{"auth":{"password":"guest","username":"guest"},"enabled":false,"url":"tcp://rabbitmq:61613/"}` | Message bus configuration for returning status to GDA/forwarding documents downstream Password may be in the form ${ENV_VAR} to be fetched from an environment variable e.g. mounted from a SealedSecret | diff --git a/helm/blueapi/values.schema.json b/helm/blueapi/values.schema.json index 58818f6c92..74deedadb2 100644 --- a/helm/blueapi/values.schema.json +++ b/helm/blueapi/values.schema.json @@ -375,6 +375,7 @@ } }, "logging": { + "description": "Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi`", "type": "object", "properties": { "graylog": { diff --git a/helm/blueapi/values.yaml b/helm/blueapi/values.yaml index a83fa74191..36a82eeb5d 100644 --- a/helm/blueapi/values.yaml +++ b/helm/blueapi/values.yaml @@ -209,7 +209,7 @@ worker: repositories: [] # - name: "dodal" # remote_url: https://github.com/DiamondLightSource/dodal.git -# -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` + # -- Configures logging. Port 12231 is the `dodal` input on graylog which will be renamed `blueapi` logging: level: "INFO" graylog: