From 5cf5baa5832b4f4b71f609295d8145b0adf03518 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Mon, 13 Jul 2026 09:24:51 +0700 Subject: [PATCH] K8s: Gate distributed component replicas on external datastore Distributor, SessionQueue and SessionMap can scale to multiple replicas only when they share state through an external datastore (Redis/Postgres). Add a seleniumGrid.component.replicaCount helper that honors components..replicas when that component's externalDatastore is enabled and otherwise forces 1, and use it in the three distributed-mode deployments. This prevents silently broken multi-replica setups (no shared state) while keeping replica counts fully settable from chart values once a datastore is configured. Co-Authored-By: Claude Opus 4.8 (1M context) --- charts/selenium-grid/templates/_helpers.tpl | 16 ++++++++++++++++ .../templates/distributor-deployment.yaml | 2 +- .../templates/session-map-deployment.yaml | 2 +- .../templates/session-queue-deployment.yaml | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/charts/selenium-grid/templates/_helpers.tpl b/charts/selenium-grid/templates/_helpers.tpl index 33784a278..03a1463a5 100644 --- a/charts/selenium-grid/templates/_helpers.tpl +++ b/charts/selenium-grid/templates/_helpers.tpl @@ -340,6 +340,22 @@ Component update strategy template {{ $spec | nindent 4 }} {{- end -}} +{{/* +Replica count for a distributed component (Distributor, SessionQueue, SessionMap). +The value from `.replicas` is honored only when the component's external datastore is +enabled, since replicas share state through it. Without an external datastore, running +multiple replicas would break the grid (no shared state), so the count is forced to 1. +Pass the component config, e.g. `.Values.components.distributor`. +*/}} +{{- define "seleniumGrid.component.replicaCount" -}} +{{- $component := . -}} +{{- if (dig "externalDatastore" "enabled" false $component) -}} +{{- max 1 ($component.replicas | int) -}} +{{- else -}} +1 +{{- end -}} +{{- end -}} + {{/* Common pod template */}} diff --git a/charts/selenium-grid/templates/distributor-deployment.yaml b/charts/selenium-grid/templates/distributor-deployment.yaml index 2cf08d0cd..39cab32b1 100644 --- a/charts/selenium-grid/templates/distributor-deployment.yaml +++ b/charts/selenium-grid/templates/distributor-deployment.yaml @@ -11,7 +11,7 @@ metadata: spec: strategy: {{- template "seleniumGrid.updateStrategy" (list $.Values.components.distributor $.Values.global.seleniumGrid) }} - replicas: {{ max 1 (.Values.components.distributor.replicas | int) }} + replicas: {{ include "seleniumGrid.component.replicaCount" .Values.components.distributor }} revisionHistoryLimit: {{ .Values.global.seleniumGrid.revisionHistoryLimit }} selector: matchLabels: diff --git a/charts/selenium-grid/templates/session-map-deployment.yaml b/charts/selenium-grid/templates/session-map-deployment.yaml index 08703dbdc..166f6fef9 100644 --- a/charts/selenium-grid/templates/session-map-deployment.yaml +++ b/charts/selenium-grid/templates/session-map-deployment.yaml @@ -11,7 +11,7 @@ metadata: spec: strategy: {{- template "seleniumGrid.updateStrategy" (list $.Values.components.sessionMap $.Values.global.seleniumGrid) }} - replicas: {{ max 1 (.Values.components.sessionMap.replicas | int) }} + replicas: {{ include "seleniumGrid.component.replicaCount" .Values.components.sessionMap }} revisionHistoryLimit: {{ .Values.global.seleniumGrid.revisionHistoryLimit }} selector: matchLabels: diff --git a/charts/selenium-grid/templates/session-queue-deployment.yaml b/charts/selenium-grid/templates/session-queue-deployment.yaml index 976ca0e25..f3a64c71c 100644 --- a/charts/selenium-grid/templates/session-queue-deployment.yaml +++ b/charts/selenium-grid/templates/session-queue-deployment.yaml @@ -11,7 +11,7 @@ metadata: spec: strategy: {{- template "seleniumGrid.updateStrategy" (list $.Values.components.sessionQueue $.Values.global.seleniumGrid) }} - replicas: {{ max 1 (.Values.components.sessionQueue.replicas | int) }} + replicas: {{ include "seleniumGrid.component.replicaCount" .Values.components.sessionQueue }} revisionHistoryLimit: {{ .Values.global.seleniumGrid.revisionHistoryLimit }} selector: matchLabels: