diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a4be3a9c95..cf740ce174 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -128,7 +128,7 @@ jobs: if: github.event.inputs.skip-build-push-image != 'true' uses: nick-invision/retry@master with: - timeout_minutes: 90 + timeout_minutes: 160 max_attempts: 3 retry_wait_seconds: 60 command: PLATFORMS="${PLATFORMS}" VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make build diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index e55138d04d..1bdd68bf8a 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -222,7 +222,7 @@ jobs: uses: nick-invision/retry@master if: matrix.build-all == true with: - timeout_minutes: 20 + timeout_minutes: 90 max_attempts: 3 retry_wait_seconds: 60 command: | diff --git a/.github/workflows/helm-chart-test.yml b/.github/workflows/helm-chart-test.yml index c2d147e992..4e838b46c3 100644 --- a/.github/workflows/helm-chart-test.yml +++ b/.github/workflows/helm-chart-test.yml @@ -197,7 +197,7 @@ jobs: - name: Build Docker images uses: nick-invision/retry@master with: - timeout_minutes: 12 + timeout_minutes: 90 max_attempts: 3 retry_wait_seconds: 60 command: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build diff --git a/.github/workflows/k8s-scaling-test.yml b/.github/workflows/k8s-scaling-test.yml index 886c14324a..4d4d2f9311 100644 --- a/.github/workflows/k8s-scaling-test.yml +++ b/.github/workflows/k8s-scaling-test.yml @@ -178,7 +178,7 @@ jobs: - name: Build Docker images uses: nick-invision/retry@master with: - timeout_minutes: 12 + timeout_minutes: 30 max_attempts: 3 retry_wait_seconds: 60 command: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index cfcc1db459..884f8a6ed5 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -78,7 +78,7 @@ jobs: - name: Build images uses: nick-invision/retry@master with: - timeout_minutes: 90 + timeout_minutes: 160 max_attempts: 3 retry_wait_seconds: 60 command: PLATFORMS="${PLATFORMS}" VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make build diff --git a/Distributor/start-selenium-grid-distributor.sh b/Distributor/start-selenium-grid-distributor.sh index 4af6dc6d5f..a004472e07 100755 --- a/Distributor/start-selenium-grid-distributor.sh +++ b/Distributor/start-selenium-grid-distributor.sh @@ -145,6 +145,10 @@ if [ ! -z "$SE_REJECT_UNSUPPORTED_CAPS" ]; then append_se_opts "--reject-unsupported-caps" "${SE_REJECT_UNSUPPORTED_CAPS}" fi +if [ ! -z "$SE_DISTRIBUTOR_SLOT_SELECTOR" ]; then + append_se_opts "--slot-selector" "${SE_DISTRIBUTOR_SLOT_SELECTOR}" +fi + if [ ! -z "$SE_NEW_SESSION_THREAD_POOL_SIZE" ]; then append_se_opts "--newsession-threadpool-size" "${SE_NEW_SESSION_THREAD_POOL_SIZE}" fi diff --git a/ENV_VARIABLES.md b/ENV_VARIABLES.md index 5478297a7b..d08fac16a9 100644 --- a/ENV_VARIABLES.md +++ b/ENV_VARIABLES.md @@ -154,3 +154,4 @@ | SE_VIDEO_MAXRATE | | | | | SE_NODE_DELETE_SESSION_ON_UI | true | Enable capability to support deleting session on Grid UI | --delete-session-on-ui | | SE_UPDATE_CHROME_COMPONENTS | | Applicable for node-chrome, standalone-chrome (arch linux/amd64). Update the latest version of Chrome and ChromeDriver at the beginning of the container startup. Read more: [#2872](https://github.com/SeleniumHQ/docker-selenium/pull/2872) | | +| SE_DISTRIBUTOR_SLOT_SELECTOR | | Full class name of non-default slot selector. This is used to select a slot in a Node once the Node has been matched. | --slot-selector | diff --git a/Hub/start-selenium-grid-hub.sh b/Hub/start-selenium-grid-hub.sh index 60daeff0cd..55db7131a7 100755 --- a/Hub/start-selenium-grid-hub.sh +++ b/Hub/start-selenium-grid-hub.sh @@ -101,6 +101,10 @@ if [ ! -z "$SE_REJECT_UNSUPPORTED_CAPS" ]; then append_se_opts "--reject-unsupported-caps" "${SE_REJECT_UNSUPPORTED_CAPS}" fi +if [ ! -z "$SE_DISTRIBUTOR_SLOT_SELECTOR" ]; then + append_se_opts "--slot-selector" "${SE_DISTRIBUTOR_SLOT_SELECTOR}" +fi + if [ ! -z "$SE_NEW_SESSION_THREAD_POOL_SIZE" ]; then append_se_opts "--newsession-threadpool-size" "${SE_NEW_SESSION_THREAD_POOL_SIZE}" fi diff --git a/Standalone/start-selenium-standalone.sh b/Standalone/start-selenium-standalone.sh index f23fa628f8..578e6eb344 100755 --- a/Standalone/start-selenium-standalone.sh +++ b/Standalone/start-selenium-standalone.sh @@ -128,6 +128,10 @@ if [ ! -z "$SE_REJECT_UNSUPPORTED_CAPS" ]; then append_se_opts "--reject-unsupported-caps" "${SE_REJECT_UNSUPPORTED_CAPS}" fi +if [ ! -z "$SE_DISTRIBUTOR_SLOT_SELECTOR" ]; then + append_se_opts "--slot-selector" "${SE_DISTRIBUTOR_SLOT_SELECTOR}" +fi + if [ ! -z "$SE_NEW_SESSION_THREAD_POOL_SIZE" ]; then append_se_opts "--newsession-threadpool-size" "${SE_NEW_SESSION_THREAD_POOL_SIZE}" fi diff --git a/charts/selenium-grid/CONFIGURATION.md b/charts/selenium-grid/CONFIGURATION.md index 401310e39a..74c3a1621c 100644 --- a/charts/selenium-grid/CONFIGURATION.md +++ b/charts/selenium-grid/CONFIGURATION.md @@ -219,6 +219,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | components.distributor.imagePullPolicy | string | `"IfNotPresent"` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | | components.distributor.imagePullSecret | string | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) | | components.distributor.newSessionThreadPoolSize | string | `nil` | Configure fixed-sized thread pool for the Distributor to create new sessions as it consumes new session requests from the queue | +| components.distributor.slotSelectorStrategy | string | `""` | Full class name of non-default slot selector. This is used to select a slot in a Node once the Node has been matched | | components.distributor.extraEnvironmentVariables | list | `[]` | Specify extra environment variables for Distributor | | components.distributor.extraEnvFrom | list | `[]` | Specify extra environment variables from ConfigMap and Secret for Distributor | | components.distributor.affinity | object | `{}` | Specify affinity for distributor pods, this overwrites global.seleniumGrid.affinity parameter | @@ -340,6 +341,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | hub.readinessProbe | object | `{"enabled":true,"failureThreshold":10,"initialDelaySeconds":12,"path":"/readyz","periodSeconds":10,"successThreshold":1,"timeoutSeconds":10}` | Readiness probe settings | | hub.livenessProbe | object | `{"enabled":true,"failureThreshold":30,"initialDelaySeconds":60,"path":"/readyz","periodSeconds":60,"successThreshold":1,"timeoutSeconds":60}` | Liveness probe settings | | hub.subPath | string | `""` | Custom sub path for the hub deployment | +| hub.slotSelectorStrategy | string | `""` | Full class name of non-default slot selector. This is used to select a slot in a Node once the Node has been matched | | hub.extraEnvironmentVariables | list | `[]` | Custom environment variables for selenium-hub | | hub.extraEnvFrom | list | `[]` | Custom environment variables by sourcing entire configMap, Secret, etc. for selenium-hub | | hub.extraVolumeMounts | list | `[]` | Extra volume mounts for Hub container | @@ -391,6 +393,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | autoscaling.enableWithExistingKEDA | bool | `false` | Enable autoscaling without automatically installing KEDA | | autoscaling.scalingType | string | `"job"` | Which type of KEDA scaling to use: job or deployment | | autoscaling.setReplicasInSpec | bool | `true` | Force remove replicas in deployment spec in case ArgoCD with AutoSync enabled will try to resolve back to desired state | +| autoscaling.slotSelectorStrategy | string | `"org.openqa.selenium.grid.distributor.selector.GreedySlotSelector"` | Strategy for Selenium Hub/Distributor select slot to assign to a new session. | | autoscaling.authenticationRef | object | `{"annotations":{"helm.sh/hook":"post-install,post-upgrade,post-rollback","helm.sh/hook-weight":"0"},"name":""}` | Specify an external KEDA TriggerAuthentication resource is used for scaler triggers config. Apply for all browser nodes | | autoscaling.useCachedMetrics | bool | `false` | Enables caching of metric values during polling interval (as specified in .spec.pollingInterval, the default: false in KEDA). | | autoscaling.triggerName | string | `""` | Set trigger name. | diff --git a/charts/selenium-grid/templates/_helpers.tpl b/charts/selenium-grid/templates/_helpers.tpl index d70ec4fbef..02da2cda16 100644 --- a/charts/selenium-grid/templates/_helpers.tpl +++ b/charts/selenium-grid/templates/_helpers.tpl @@ -202,6 +202,16 @@ based on sum of maxReplicaCount of all enabled Nodes in autoscaling {{- $threadPoolSize -}} {{- end -}} +{{- define "seleniumGrid.autoscaling.distributor.slotSelector" -}} +{{- $slotSelector := "" -}} +{{- if eq (include "seleniumGrid.useKEDA" $) "true" -}} +{{- $slotSelector = $.Values.autoscaling.slotSelectorStrategy -}} +{{- else -}} +{{- $slotSelector = $.Values.isolateComponents | ternary $.Values.components.distributor.slotSelectorStrategy $.Values.hub.slotSelectorStrategy -}} +{{- end -}} +{{- $slotSelector -}} +{{- end -}} + {{/* Common autoscaling spec template */}} diff --git a/charts/selenium-grid/templates/distributor-deployment.yaml b/charts/selenium-grid/templates/distributor-deployment.yaml index 841df9f711..75c0ab1a03 100644 --- a/charts/selenium-grid/templates/distributor-deployment.yaml +++ b/charts/selenium-grid/templates/distributor-deployment.yaml @@ -73,6 +73,10 @@ spec: - name: SE_NEW_SESSION_THREAD_POOL_SIZE value: '{{ template "seleniumGrid.autoscaling.distributor.threadPoolSize" $ }}' {{- end }} + {{- if not (empty (include "seleniumGrid.autoscaling.distributor.slotSelector" $)) }} + - name: SE_DISTRIBUTOR_SLOT_SELECTOR + value: {{ include "seleniumGrid.autoscaling.distributor.slotSelector" $ | quote }} + {{- end }} {{- with .Values.components.extraEnvironmentVariables }} {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} diff --git a/charts/selenium-grid/templates/hub-deployment.yaml b/charts/selenium-grid/templates/hub-deployment.yaml index faf983a87e..d7e32d4608 100644 --- a/charts/selenium-grid/templates/hub-deployment.yaml +++ b/charts/selenium-grid/templates/hub-deployment.yaml @@ -130,6 +130,10 @@ spec: - name: SE_NEW_SESSION_THREAD_POOL_SIZE value: '{{ template "seleniumGrid.autoscaling.distributor.threadPoolSize" $ }}' {{- end }} + {{- if not (empty (include "seleniumGrid.autoscaling.distributor.slotSelector" $)) }} + - name: SE_DISTRIBUTOR_SLOT_SELECTOR + value: {{ include "seleniumGrid.autoscaling.distributor.slotSelector" $ | quote }} + {{- end }} {{- with .Values.hub.extraEnvironmentVariables }} {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} diff --git a/charts/selenium-grid/values.yaml b/charts/selenium-grid/values.yaml index 2d60a06a55..7768f90f44 100644 --- a/charts/selenium-grid/values.yaml +++ b/charts/selenium-grid/values.yaml @@ -529,6 +529,8 @@ components: # -- Configure fixed-sized thread pool for the Distributor to create new sessions as it consumes new session requests from the queue newSessionThreadPoolSize: + # -- Full class name of non-default slot selector. This is used to select a slot in a Node once the Node has been matched + slotSelectorStrategy: "" # -- Specify extra environment variables for Distributor extraEnvironmentVariables: [] # -- Specify extra environment variables from ConfigMap and Secret for Distributor @@ -885,6 +887,8 @@ hub: successThreshold: 1 # -- Custom sub path for the hub deployment subPath: "" + # -- Full class name of non-default slot selector. This is used to select a slot in a Node once the Node has been matched + slotSelectorStrategy: "" # -- Custom environment variables for selenium-hub extraEnvironmentVariables: [] # - name: SE_JAVA_OPTS @@ -1015,6 +1019,12 @@ autoscaling: scalingType: job # -- Force remove replicas in deployment spec in case ArgoCD with AutoSync enabled will try to resolve back to desired state setReplicasInSpec: true + # By default, it is "org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector". This is ensuring load balancing sessions across all available nodes. + # New strategy "org.openqa.selenium.grid.distributor.selector.GreedySlotSelector". This might be helpful in case autoscaling overprovisioned with max sessions greater than 1 per node. + # Ensure all slots in a node are filled with sessions before selecting the next available node. Note this is available since Selenium Server 4.34.0. + # Change this default chart value if you prefer default strategy or using this chart with older Selenium Server versions. + # -- Strategy for Selenium Hub/Distributor select slot to assign to a new session. + slotSelectorStrategy: "org.openqa.selenium.grid.distributor.selector.GreedySlotSelector" # -- Specify an external KEDA TriggerAuthentication resource is used for scaler triggers config. Apply for all browser nodes authenticationRef: name: "" diff --git a/scripts/generate_list_env_vars/description.yaml b/scripts/generate_list_env_vars/description.yaml index e46f88f6e1..e13a32fe25 100644 --- a/scripts/generate_list_env_vars/description.yaml +++ b/scripts/generate_list_env_vars/description.yaml @@ -473,3 +473,7 @@ Update the latest version of Chrome and ChromeDriver at the beginning of the container startup. Read more: [#2872](https://github.com/SeleniumHQ/docker-selenium/pull/2872)' cli: '' +- name: SE_DISTRIBUTOR_SLOT_SELECTOR + description: Full class name of non-default slot selector. This is used to select + a slot in a Node once the Node has been matched. + cli: --slot-selector diff --git a/scripts/generate_list_env_vars/value.yaml b/scripts/generate_list_env_vars/value.yaml index 91ea2b6910..ba22ffa33a 100644 --- a/scripts/generate_list_env_vars/value.yaml +++ b/scripts/generate_list_env_vars/value.yaml @@ -18,6 +18,8 @@ default: '' - name: SE_DISTRIBUTOR_PORT default: '5553' +- name: SE_DISTRIBUTOR_SLOT_SELECTOR + default: '' - name: SE_DRAIN_AFTER_SESSION_COUNT default: '0' - name: SE_ENABLE_BROWSER_LEFTOVERS_CLEANUP