Skip to content

Commit 0ac93a9

Browse files
authored
Experimental: Selenium Grid scaler with different nodeMaxSessions per node (#2402)
Signed-off-by: Viet Nguyen Duc <[email protected]>
1 parent 6c4f76e commit 0ac93a9

File tree

11 files changed

+73
-7
lines changed

11 files changed

+73
-7
lines changed

.keda/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ docker pull selenium/keda-admission-webhooks:2.15.1-selenium-grid-20240907
2020

2121
Besides that, you also can use image tag `latest` or `nightly`.
2222

23-
If you are deploying KEDA core using their official Helm chart, you can overwrite the image registry and tag by providing the following values in the `values.yaml` file. For example:
23+
If you are deploying KEDA core using their official Helm [chart](https://github.com/kedacore/charts), you can overwrite the image registry and tag by providing the following values in the `values.yaml` file. For example:
2424

2525
```yaml
2626
image:

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ chart_test_autoscaling_disabled:
913913
chart_test_autoscaling_deployment_https:
914914
PLATFORMS=$(PLATFORMS) CHART_FULL_DISTRIBUTED_MODE=true CHART_ENABLE_BASIC_AUTH=true \
915915
SECURE_INGRESS_ONLY_DEFAULT=true INGRESS_DISABLE_USE_HTTP2=true SELENIUM_GRID_PROTOCOL=https CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PORT=443 \
916-
SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=1 \
916+
SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=1 MAX_SESSIONS_FIREFOX=3 MAX_SESSIONS_EDGE=2 MAX_SESSIONS_CHROME=1 \
917917
VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) \
918918
TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_basicAuth_secureIngress_defaultCerts_ingressHostName_disableHttp2_autoScaling_scaledObject_subPath.yaml" \
919919
./tests/charts/make/chart_test.sh DeploymentAutoscaling
@@ -929,6 +929,7 @@ chart_test_autoscaling_deployment:
929929
chart_test_autoscaling_job_https:
930930
PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_BASIC_AUTH=true \
931931
SECURE_CONNECTION_SERVER=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 SUB_PATH=/ \
932+
MAX_SESSIONS_FIREFOX=1 MAX_SESSIONS_EDGE=2 MAX_SESSIONS_CHROME=3 \
932933
VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) EXTERNAL_UPLOADER_CONFIG=true \
933934
TEMPLATE_OUTPUT_FILENAME="k8s_prefixSelenium_basicAuth_secureServer_autoScaling_scaledJob_existingKEDA.yaml" \
934935
./tests/charts/make/chart_test.sh JobAutoscaling

Video/video.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ else
210210
if [[ "${endpoint_status}" = "401" ]]; then
211211
echo "$(date +%FT%T%Z) [${process_name}] - GraphQL endpoint requires authentication, please set env variables SE_ROUTER_USERNAME and SE_ROUTER_PASSWORD"
212212
elif [[ "${endpoint_status}" = "404" ]]; then
213-
echo "$(date +%FT%T%Z) [${process_name}] -GraphQL endpoint could not be found, please check the endpoint ${endpoint_url}"
213+
echo "$(date +%FT%T%Z) [${process_name}] - GraphQL endpoint could not be found, please check the endpoint ${endpoint_url}"
214214
fi
215215
echo "$(date +%FT%T%Z) [${process_name}] - Start recording: $caps_se_video_record, video file name: $video_file_name"
216216
log_node_response

charts/selenium-grid/CONFIGURATION.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
3232
| global.seleniumGrid.imageTag | string | `"4.24.0-20240907"` | Image tag for all selenium components |
3333
| global.seleniumGrid.nodesImageTag | string | `"4.24.0-20240907"` | Image tag for browser's nodes |
3434
| global.seleniumGrid.videoImageTag | string | `"ffmpeg-7.0.2-20240907"` | Image tag for browser's video recorder |
35-
| global.seleniumGrid.kubectlImage | string | `"jitesoft/kubectl:latest"` | kubectl image is used to execute kubectl commands in utility jobs |
35+
| global.seleniumGrid.kubectlImage | string | `"bitnami/kubectl:latest"` | kubectl image is used to execute kubectl commands in utility jobs |
3636
| global.seleniumGrid.imagePullSecret | string | `""` | Pull secret for all components, can be overridden individually |
3737
| global.seleniumGrid.logLevel | string | `"INFO"` | Log level for all components. Possible values describe here: https://www.selenium.dev/documentation/grid/configuration/cli_options/#logging |
3838
| global.seleniumGrid.defaultNodeStartupProbe | string | `"exec"` | Set default startup probe method for all nodes (supplied values: httpGet, exec). If not set, the default is httpGet |
@@ -46,6 +46,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
4646
| global.seleniumGrid.updateStrategy.rollingUpdate | object | `{"maxSurge":1,"maxUnavailable":0}` | Specify for strategy RollingUpdate |
4747
| global.seleniumGrid.affinity | object | `{}` | Specify affinity for all components, can be overridden individually |
4848
| global.seleniumGrid.topologySpreadConstraints | list | `[]` | Specify topologySpreadConstraints for all components, can be overridden individually |
49+
| global.seleniumGrid.nodeMaxSessions | int | `1` | Specify number of max sessions per node. Can be overridden by individual component (this is also set to scaler trigger parameter `nodeMaxSessions` if `autoscaling` is enabled) |
4950
| tls.nameOverride | string | `nil` | Name of external secret containing the TLS certificate and key |
5051
| tls.enabled | bool | `false` | Enable or disable TLS for the server components (and ingress proxy) |
5152
| tls.ingress.enabled | bool | `false` | Enable or disable TLS for the ingress proxy only |
@@ -362,6 +363,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
362363
| chromeNode.lifecycle | object | `{}` | Define postStart and preStop events. This overwrites the defined preStop in deregisterLifecycle if any |
363364
| chromeNode.extraVolumeMounts | list | `[]` | Extra volume mounts for chrome-node container |
364365
| chromeNode.extraVolumes | list | `[]` | Extra volumes for chrome-node pod |
366+
| chromeNode.nodeMaxSessions | string | `nil` | Override the number of max sessions per node |
365367
| chromeNode.scaledOptions | string | `nil` | Override the scaled options for chrome nodes |
366368
| chromeNode.scaledJobOptions | string | `nil` | Override the scaledJobOptions for chrome nodes |
367369
| chromeNode.scaledObjectOptions | string | `nil` | Override the scaledObjectOptions for chrome nodes |
@@ -411,6 +413,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
411413
| firefoxNode.lifecycle | object | `{}` | Define postStart and preStop events. This overwrites the defined preStop in deregisterLifecycle if any |
412414
| firefoxNode.extraVolumeMounts | list | `[]` | Extra volume mounts for firefox-node container |
413415
| firefoxNode.extraVolumes | list | `[]` | Extra volumes for firefox-node pod |
416+
| firefoxNode.nodeMaxSessions | string | `nil` | Override the number of max sessions per node |
414417
| firefoxNode.scaledOptions | string | `nil` | Override the scaled options for firefox nodes |
415418
| firefoxNode.scaledJobOptions | string | `nil` | Override the scaledJobOptions for firefox nodes |
416419
| firefoxNode.scaledObjectOptions | string | `nil` | Override the scaledObjectOptions for firefox nodes |
@@ -460,6 +463,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
460463
| edgeNode.lifecycle | object | `{}` | Define postStart and preStop events. This overwrites the defined preStop in deregisterLifecycle if any |
461464
| edgeNode.extraVolumeMounts | list | `[]` | Extra volume mounts for edge-node container |
462465
| edgeNode.extraVolumes | list | `[]` | Extra volumes for edge-node pod |
466+
| edgeNode.nodeMaxSessions | string | `nil` | Override the number of max sessions per node |
463467
| edgeNode.scaledOptions | string | `nil` | Override the scaled options for edge nodes |
464468
| edgeNode.scaledJobOptions | string | `nil` | Override the scaledJobOptions for edge nodes |
465469
| edgeNode.scaledObjectOptions | string | `nil` | Override the scaledObjectOptions for edge nodes |

charts/selenium-grid/templates/_helpers.tpl

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ Common autoscaling spec template
207207
*/}}
208208
{{- define "seleniumGrid.autoscalingTemplate" -}}
209209
{{- $spec := toYaml (dict) -}}
210+
{{- $nodeMaxSessions := default $.Values.global.seleniumGrid.nodeMaxSessions .node.nodeMaxSessions | int64 -}}
210211
{{/* Merge with precedence from right to left */}}
211212
{{- with $.Values.autoscaling.scaledOptions -}}
212213
{{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}}
@@ -239,7 +240,7 @@ Common autoscaling spec template
239240
triggers:
240241
- type: selenium-grid
241242
metadata:
242-
triggerIndex: '{{ default $.Values.autoscaling.scaledOptions.minReplicaCount (.node.scaledOptions).minReplicaCount }}'
243+
nodeMaxSessions: {{ $nodeMaxSessions | quote }}
243244
{{- with .node.hpa }}
244245
{{- tpl (toYaml .) $ | nindent 6 }}
245246
{{- end }}
@@ -278,6 +279,7 @@ Common pod template
278279
{{- $nodeImageTag := default $.Values.global.seleniumGrid.nodesImageTag .node.imageTag -}}
279280
{{- $videoImageRegistry := default $.Values.global.seleniumGrid.imageRegistry $.Values.videoRecorder.imageRegistry -}}
280281
{{- $videoImageTag := default $.Values.global.seleniumGrid.videoImageTag $.Values.videoRecorder.imageTag -}}
282+
{{- $nodeMaxSessions := default $.Values.global.seleniumGrid.nodeMaxSessions .node.nodeMaxSessions | int64 -}}
281283
template:
282284
metadata:
283285
labels:
@@ -329,6 +331,14 @@ template:
329331
image: {{ printf "%s/%s:%s" $nodeImageRegistry .node.imageName $nodeImageTag }}
330332
imagePullPolicy: {{ .node.imagePullPolicy }}
331333
env:
334+
- name: SE_NODE_MAX_SESSIONS
335+
value: {{ $nodeMaxSessions | quote }}
336+
{{- if gt $nodeMaxSessions 1 }}
337+
- name: SE_NODE_OVERRIDE_MAX_SESSIONS
338+
value: "true"
339+
{{- end }}
340+
- name: SE_DRAIN_AFTER_SESSION_COUNT
341+
value: {{ and (eq (include "seleniumGrid.useKEDA" $) "true") (eq .Values.autoscaling.scalingType "job") | ternary $nodeMaxSessions 0 | quote }}
332342
- name: SE_NODE_CONTAINER_NAME
333343
valueFrom:
334344
fieldRef:
@@ -469,6 +479,10 @@ template:
469479
image: {{ printf "%s/%s:%s" $videoImageRegistry $.Values.videoRecorder.imageName $videoImageTag }}
470480
imagePullPolicy: {{ $.Values.videoRecorder.imagePullPolicy }}
471481
env:
482+
- name: SE_NODE_MAX_SESSIONS
483+
value: {{ $nodeMaxSessions | quote }}
484+
- name: SE_DRAIN_AFTER_SESSION_COUNT
485+
value: {{ and (eq (include "seleniumGrid.useKEDA" $) "true") (eq .Values.autoscaling.scalingType "job") | ternary $nodeMaxSessions 0 | quote }}
472486
- name: SE_NODE_PORT
473487
value: {{ .node.port | quote }}
474488
- name: DISPLAY_CONTAINER_NAME

charts/selenium-grid/templates/node-configmap.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ data:
2323
{{- end }}
2424
NODE_CONFIG_DIRECTORY: '{{ $.Values.nodeConfigMap.extraScriptsDirectory }}'
2525
SE_SUB_PATH: '{{ template "seleniumGrid.url.subPath" $ }}'
26-
SE_DRAIN_AFTER_SESSION_COUNT: '{{- and (eq (include "seleniumGrid.useKEDA" .) "true") (eq .Values.autoscaling.scalingType "job") | ternary "1" "0" -}}'
2726
{{- if $.Values.videoRecorder.enabled }}
2827
SE_VIDEO_CONTAINER_NAME: {{ $.Values.videoRecorder.name | quote }}
2928
{{- end }}

charts/selenium-grid/values.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ global:
1313
# -- Image tag for browser's video recorder
1414
videoImageTag: ffmpeg-7.0.2-20240907
1515
# -- kubectl image is used to execute kubectl commands in utility jobs
16-
kubectlImage: jitesoft/kubectl:latest
16+
kubectlImage: bitnami/kubectl:latest
1717
# -- Pull secret for all components, can be overridden individually
1818
imagePullSecret: ""
1919
# -- Log level for all components. Possible values describe here: https://www.selenium.dev/documentation/grid/configuration/cli_options/#logging
@@ -48,6 +48,8 @@ global:
4848
# topologyKey: kubernetes.io/hostname
4949
# whenUnsatisfiable: DoNotSchedule
5050
# Note: If not define labelSelector, it will be added automatically based on "app" label in each component
51+
# -- Specify number of max sessions per node. Can be overridden by individual component (this is also set to scaler trigger parameter `nodeMaxSessions` if `autoscaling` is enabled)
52+
nodeMaxSessions: 1
5153

5254
tls:
5355
# -- Name of external secret containing the TLS certificate and key
@@ -1006,6 +1008,8 @@ chromeNode:
10061008
# persistentVolumeClaim:
10071009
# claimName: my-pv-claim
10081010

1011+
# -- Override the number of max sessions per node
1012+
nodeMaxSessions:
10091013
# -- Override the scaled options for chrome nodes
10101014
scaledOptions:
10111015
# -- Override the scaledJobOptions for chrome nodes
@@ -1185,6 +1189,8 @@ firefoxNode:
11851189
# persistentVolumeClaim:
11861190
# claimName: my-pv-claim
11871191

1192+
# -- Override the number of max sessions per node
1193+
nodeMaxSessions:
11881194
# -- Override the scaled options for firefox nodes
11891195
scaledOptions:
11901196
# -- Override the scaledJobOptions for firefox nodes
@@ -1363,6 +1369,8 @@ edgeNode:
13631369
# persistentVolumeClaim:
13641370
# claimName: my-pv-claim
13651371

1372+
# -- Override the number of max sessions per node
1373+
nodeMaxSessions:
13661374
# -- Override the scaled options for edge nodes
13671375
scaledOptions:
13681376
# -- Override the scaledJobOptions for edge nodes

tests/charts/make/chart_test.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ else
4949
fi
5050
EXTERNAL_TLS_SECRET_NAME=${EXTERNAL_TLS_SECRET_NAME:-"external-tls-secret"}
5151
SELENIUM_ENABLE_MANAGED_DOWNLOADS=${SELENIUM_ENABLE_MANAGED_DOWNLOADS:-"true"}
52+
MAX_SESSIONS_CHROME=${MAX_SESSIONS_CHROME:-"1"}
53+
MAX_SESSIONS_FIREFOX=${MAX_SESSIONS_FIREFOX:-"1"}
54+
MAX_SESSIONS_EDGE=${MAX_SESSIONS_EDGE:-"1"}
5255

5356
cleanup() {
5457
# Get the list of pods
@@ -126,6 +129,9 @@ HELM_COMMAND_SET_IMAGES=" \
126129
--set global.seleniumGrid.httpLogs=${CHART_ENABLE_TRACING} \
127130
--set isolateComponents=${CHART_FULL_DISTRIBUTED_MODE} \
128131
--set global.seleniumGrid.logLevel=${LOG_LEVEL} \
132+
--set chromeNode.nodeMaxSessions=${MAX_SESSIONS_CHROME} \
133+
--set firefoxNode.nodeMaxSessions=${MAX_SESSIONS_FIREFOX} \
134+
--set edgeNode.nodeMaxSessions=${MAX_SESSIONS_EDGE} \
129135
"
130136

131137
if [ "${SELENIUM_GRID_AUTOSCALING}" = "true" ] && [ "${TEST_EXISTING_KEDA}" = "true" ]; then

tests/charts/templates/render/dummy.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ global:
1717
- maxSkew: 4
1818
topologyKey: kubernetes.io/hostname
1919
whenUnsatisfiable: DoNotSchedule
20+
nodeMaxSessions: 3
2021

2122
autoscaling:
2223
enableWithExistingKEDA: true
@@ -95,11 +96,13 @@ components:
9596
serviceType: NodePort
9697

9798
chromeNode:
99+
nodeMaxSessions: 2
98100
annotations:
99101
"restartOnUpdate": "true"
100102
terminationGracePeriodSeconds: 7200
101103

102104
firefoxNode:
105+
nodeMaxSessions: 1
103106
annotations:
104107
"restartOnUpdate": "true"
105108
terminationGracePeriodSeconds: 720

tests/charts/templates/render/dummy_solution.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ global:
1717
- maxSkew: 4
1818
topologyKey: kubernetes.io/hostname
1919
whenUnsatisfiable: DoNotSchedule
20+
nodeMaxSessions: 3
2021

2122
selenium-grid:
2223
autoscaling:
@@ -86,10 +87,12 @@ selenium-grid:
8687
serviceType: NodePort
8788

8889
chromeNode:
90+
nodeMaxSessions: 2
8991
affinity: *affinity
9092
terminationGracePeriodSeconds: 7200
9193

9294
firefoxNode:
95+
nodeMaxSessions: 1
9396
affinity: *affinity
9497
terminationGracePeriodSeconds: 720
9598

0 commit comments

Comments
 (0)