Skip to content

Commit ea7b913

Browse files
authored
chart(feat): add graphql metrics exporter for monitoring (#2425)
1 parent 1a9aa38 commit ea7b913

19 files changed

+244
-23
lines changed

Diff for: Base/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM ubuntu:noble-20240827.1
1+
FROM ubuntu:noble-20240904.1
22
ARG AUTHORS=SeleniumHQ
33
LABEL authors="${AUTHORS} <[email protected]>"
44
LABEL org.opencontainers.image.source="https://github.com/${AUTHORS}/docker-selenium"

Diff for: Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ SBOM_OUTPUT := $(or $(SBOM_OUTPUT),$(SBOM_OUTPUT),package_versions.txt)
2929
KEDA_TAG_PREV_VERSION := $(or $(KEDA_TAG_PREV_VERSION),$(KEDA_TAG_PREV_VERSION),2.15.1-selenium-grid)
3030
KEDA_TAG_VERSION := $(or $(KEDA_TAG_VERSION),$(KEDA_TAG_VERSION),2.15.1-selenium-grid)
3131
KEDA_BASED_NAME := $(or $(KEDA_BASED_NAME),$(KEDA_BASED_NAME),ndviet)
32-
KEDA_BASED_TAG := $(or $(KEDA_BASED_TAG),$(KEDA_BASED_TAG),2.15.1-selenium-grid)
32+
KEDA_BASED_TAG := $(or $(KEDA_BASED_TAG),$(KEDA_BASED_TAG),2.15.1-selenium-grid-20241007)
3333

3434
all: hub \
3535
distributor \

Diff for: NodeBase/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ RUN --mount=type=secret,id=SEL_PASSWD \
118118
&& unzip -x websockify.zip \
119119
&& rm websockify.zip \
120120
&& mv websockify-${WEBSOCKIFY_VERSION} /opt/bin/noVNC/utils/websockify \
121+
&& chmod +x /opt/bin/noVNC/utils/websockify/run \
121122
&& rm -rf /opt/bin/noVNC/utils/websockify/docker /opt/bin/noVNC/utils/websockify/tests \
122123
#========================================================================
123124
# Run this command for executable file permissions for /dev/shm when #

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![Release Charts](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/helm-chart-release.yml/badge.svg)](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/helm-chart-release.yml)
44
[![Nightly](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/nightly.yml/badge.svg)](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/nightly.yml)
55
[![Update Dev/Beta Browser Images](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/update-dev-beta-browser-images.yml/badge.svg)](https://github.com/SeleniumHQ/docker-selenium/actions/workflows/update-dev-beta-browser-images.yml)
6+
[![Releases downloads](https://img.shields.io/github/downloads/seleniumhq/docker-selenium/total.svg)](https://github.com/SeleniumHQ/docker-selenium/releases)
67

78
# Docker images for the Selenium Grid Server
89

Diff for: charts/selenium-grid/CONFIGURATION.md

+19-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
7979
| serviceAccount.create | bool | `true` | Create a service account for all components. If using an external service account, set to false and provide its name in `nameOverride` below |
8080
| serviceAccount.nameOverride | string | `nil` | Override to use an external service account |
8181
| serviceAccount.annotations | object | `{}` | Annotations for the service account |
82-
| rbacRole | object | `{"annotations":{},"create":true,"nameOverride":null,"rules":[{"apiGroups":["keda.sh"],"resources":["scaledjobs"],"verbs":["get","list","patch","update","delete"]},{"apiGroups":["keda.sh"],"resources":["scaledobjects"],"verbs":["get","list","patch","update","delete"]},{"apiGroups":["autoscaling"],"resources":["horizontalpodautoscalers"],"verbs":["get","list","patch","update","delete"]}]}` | RBAC settings for patching finalizers KEDA scaled resources |
82+
| rbacRole | object | `{"annotations":{},"create":true,"nameOverride":null,"rules":[{"apiGroups":["keda.sh"],"resources":["scaledjobs"],"verbs":["get","list","patch","update","delete"]},{"apiGroups":["keda.sh"],"resources":["scaledobjects"],"verbs":["get","list","patch","update","delete"]},{"apiGroups":["keda.sh"],"resources":["triggerauthentication"],"verbs":["get","list","patch","update","delete"]},{"apiGroups":["autoscaling"],"resources":["horizontalpodautoscalers"],"verbs":["get","list","patch","update","delete"]}]}` | RBAC settings for patching finalizers KEDA scaled resources |
8383
| rbacRole.create | bool | `true` | Enable to create RBAC role to access few KEDA resources. If using an external role, set to false and provide its name in `nameOverride` below |
8484
| rbacRole.nameOverride | string | `nil` | Override resource name or provide an external role name |
8585
| rbacRoleBinding | object | `{"annotations":{},"create":true,"nameOverride":null,"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"Role"},"subjects":[{"kind":"ServiceAccount"}]}` | RBAC role binding settings for patching finalizers KEDA scaled resources |
@@ -307,6 +307,22 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
307307
| tracing.ingress.paths | list | `[{"backend":{"service":{"name":"{{ .Release.Name }}-jaeger-query","port":{"number":16686}}},"path":"/jaeger","pathType":"Prefix"}]` | Configure paths for Jaeger ingress resource |
308308
| monitoring.enabled | bool | `false` | |
309309
| monitoring.enabledWithExistingAgent | bool | `false` | |
310+
| monitoring.exporter.nameOverride | string | `""` | |
311+
| monitoring.exporter.imageRegistry | string | `"ricardbejarano"` | |
312+
| monitoring.exporter.imageName | string | `"graphql_exporter"` | |
313+
| monitoring.exporter.imageTag | string | `"latest"` | |
314+
| monitoring.exporter.imagePullSecret | string | `""` | Custom pull secret for container in patch job |
315+
| monitoring.exporter.annotations | object | `{}` | |
316+
| monitoring.exporter.port | int | `9199` | |
317+
| monitoring.exporter.service.enabled | bool | `true` | Create a service for exporter |
318+
| monitoring.exporter.service.type | string | `"ClusterIP"` | Service type |
319+
| monitoring.exporter.service.loadBalancerIP | string | `""` | Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) |
320+
| monitoring.exporter.service.nodePort | int | `30199` | Node port for service |
321+
| monitoring.exporter.service.annotations | object | `{}` | Annotations for exporter service |
322+
| monitoring.exporter.replicas | int | `1` | |
323+
| monitoring.additionalScrapeConfigs.key | string | `""` | |
324+
| monitoring.additionalScrapeConfigs.value | string | `""` | |
325+
| monitoring.annotations | object | `{}` | |
310326
| autoscaling.enabled | bool | `false` | Enable autoscaling. Implies installing KEDA |
311327
| autoscaling.enableWithExistingKEDA | bool | `false` | Enable autoscaling without automatically installing KEDA |
312328
| autoscaling.scalingType | string | `"job"` | Which type of KEDA scaling to use: job or deployment |
@@ -318,7 +334,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
318334
| autoscaling.patchObjectFinalizers.annotations | object | `{"helm.sh/hook":"post-install,post-upgrade,post-rollback,pre-delete","helm.sh/hook-delete-policy":"hook-succeeded,before-hook-creation","helm.sh/hook-weight":"-1"}` | Annotations for patch job |
319335
| autoscaling.patchObjectFinalizers.serviceAccount | string | `""` | Define an external service account name contains permissions to patch KEDA scaled resources |
320336
| autoscaling.patchObjectFinalizers.imagePullSecret | string | `""` | Custom pull secret for container in patch job |
321-
| autoscaling.patchObjectFinalizers.resources | object | `{"limits":{"cpu":"50m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}` | Define resources for container in patch job |
337+
| autoscaling.patchObjectFinalizers.resources | object | `{"limits":{"cpu":"200m","memory":"500Mi"},"requests":{"cpu":"100m","memory":"200Mi"}}` | Define resources for container in patch job |
322338
| autoscaling.scaledOptions | object | `{"maxReplicaCount":8,"minReplicaCount":0,"pollingInterval":10}` | Options for KEDA scaled resources (keep only common options used for both ScaledJob and ScaledObject) |
323339
| autoscaling.scaledOptions.minReplicaCount | int | `0` | Minimum number of replicas |
324340
| autoscaling.scaledOptions.maxReplicaCount | int | `8` | Maximum number of replicas |
@@ -512,6 +528,6 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes
512528
| keda.http.timeout | int | `60000` | |
513529
| keda.webhooks | object | `{"enabled":false}` | Enable KEDA admission webhooks component |
514530
| ingress-nginx | object | `{"controller":{"admissionWebhooks":{"enabled":false}}}` | Configuration for dependency chart ingress-nginx |
515-
| kube-prometheus-stack | object | `{"cleanPrometheusOperatorObjectNames":true}` | Configuration for dependency chart kube-prometheus-stack |
531+
| kube-prometheus-stack | object | `{"cleanPrometheusOperatorObjectNames":true,"prometheus":{"prometheusSpec":{"additionalConfig":{"additionalScrapeConfigs":{"key":"{{ template \"seleniumGrid.monitoring.scrape.key\" $ }}","name":"{{ template \"seleniumGrid.monitoring.exporter.fullname\" $ }}"}}}}}` | Configuration for dependency chart kube-prometheus-stack |
516532
| jaeger | object | `{"agent":{"enabled":false},"allInOne":{"enabled":true,"extraEnv":[{"name":"QUERY_BASE_PATH","value":"/jaeger"}]},"collector":{"enabled":false},"provisionDataStore":{"cassandra":false},"query":{"enabled":false},"storage":{"type":"badger"}}` | Configuration for dependency chart jaeger |
517533

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
- job_name: "selenium-grid-analytics"
2+
metrics_path: "/query"
3+
bearer_token: ""
4+
params:
5+
endpoint:
6+
- '{{ template "seleniumGrid.monitoring.graphqlURL" $ }}'
7+
query:
8+
- |
9+
{ grid { sessionCount, maxSession, totalSlots, nodeCount, sessionQueueSize }, nodesInfo { nodes { id, status, sessionCount, maxSession, slotCount, stereotypes, sessions { id, capabilities, sessionDurationMillis, slot { id, stereotype } } } }, sessionsInfo { sessionQueueRequests } }
10+
zoneTag: []
11+
tls_config:
12+
insecure_skip_verify: true
13+
static_configs:
14+
- targets:
15+
- '{{ template "seleniumGrid.monitoring.exporter.fullname" $ }}.{{ .Release.Namespace }}:{{ $.Values.monitoring.exporter.port }}'

Diff for: charts/selenium-grid/templates/_helpers.tpl

+7
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,13 @@ Graphql Url of the hub or the router
659659
{{- printf "%s/graphql" (include "seleniumGrid.server.url" $) -}}
660660
{{- end -}}
661661

662+
{{/*
663+
Graphql Url for internal monitoring exporter
664+
*/}}
665+
{{- define "seleniumGrid.monitoring.graphqlURL" -}}
666+
{{- printf "%s://%s%s%s%s/graphql" (include "seleniumGrid.server.url.schema" .) (include "seleniumGrid.url.basicAuth" .) (include "seleniumGrid.server.url.host" .) (include "seleniumGrid.server.url.port" .) (include "seleniumGrid.url.subPath" .) -}}
667+
{{- end -}}
668+
662669
{{- define "seleniumGrid.url.schema" -}}
663670
{{- $schema := "http" -}}
664671
{{- if or (eq (include "seleniumGrid.server.secureConnection" $) "true") (eq (include "seleniumGrid.ingress.secureConnection" $) "true") -}}

Diff for: charts/selenium-grid/templates/_nameHelpers.tpl

+14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ component.autoscaling: "{{ .Release.Name }}"
5656
{{- end -}}
5757
{{- end -}}
5858

59+
{{/*
60+
Selenium metrics exporter fullname
61+
*/}}
62+
{{- define "seleniumGrid.monitoring.exporter.fullname" -}}
63+
{{- tpl (default (include "seleniumGrid.component.name" (list "selenium-metrics-exporter" $)) ($.Values.monitoring).exporter.nameOverride) $ | trunc 63 | trimSuffix "-" -}}
64+
{{- end -}}
65+
66+
{{/*
67+
Selenium metrics scrape key in secret resource
68+
*/}}
69+
{{- define "seleniumGrid.monitoring.scrape.key" -}}
70+
{{- tpl (default (include "seleniumGrid.component.name" (list "selenium-grid-scrape" $)) ($.Values.monitoring).additionalScrapeConfigs.key) $ | trunc 63 | trimSuffix "-" -}}
71+
{{- end -}}
72+
5973
{{/*
6074
Selenium Hub fullname
6175
*/}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{{- if eq (include "seleniumGrid.monitoring.enabled" $) "true" }}
2+
apiVersion: apps/v1
3+
kind: Deployment
4+
metadata:
5+
name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
6+
namespace: {{ .Release.Namespace }}
7+
labels: &exporter_labels
8+
app: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
9+
app.kubernetes.io/name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
10+
{{- include "seleniumGrid.commonLabels" . | nindent 4 }}
11+
spec:
12+
replicas: {{ .Values.monitoring.exporter.replicas }}
13+
selector:
14+
matchLabels:
15+
app: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
16+
app.kubernetes.io/name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
17+
template:
18+
metadata:
19+
labels: *exporter_labels
20+
annotations:
21+
{{- with .Values.monitoring.exporter.annotations }}
22+
{{- toYaml . | nindent 8 }}
23+
{{- end }}
24+
spec:
25+
{{- if or .Values.global.seleniumGrid.imagePullSecret .Values.monitoring.exporter.imagePullSecret }}
26+
imagePullSecrets:
27+
- name: {{ default .Values.global.seleniumGrid.imagePullSecret .Values.monitoring.exporter.imagePullSecret }}
28+
{{- end }}
29+
containers:
30+
- name: graphql-exporter
31+
{{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.monitoring.exporter.imageRegistry }}
32+
image: {{ printf "%s/%s:%s" $imageRegistry .Values.monitoring.exporter.imageName .Values.monitoring.exporter.imageTag | quote }}
33+
ports:
34+
- containerPort: {{ .Values.monitoring.exporter.port }}
35+
{{- end }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- if eq (include "seleniumGrid.monitoring.enabled" $) "true" }}
2+
apiVersion: v1
3+
kind: Service
4+
metadata:
5+
name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
6+
namespace: {{ .Release.Namespace }}
7+
labels:
8+
app: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
9+
app.kubernetes.io/name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
10+
{{- include "seleniumGrid.commonLabels" . | nindent 4 }}
11+
spec:
12+
selector:
13+
app: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
14+
app.kubernetes.io/name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
15+
type: {{ .Values.monitoring.exporter.service.type }}
16+
{{- if and (eq .Values.monitoring.exporter.service.type "LoadBalancer") ( .Values.monitoring.exporter.service.loadBalancerIP ) }}
17+
loadBalancerIP: {{ .Values.monitoring.exporter.service.loadBalancerIP }}
18+
{{- end }}
19+
ports:
20+
- name: http-port
21+
protocol: TCP
22+
port: {{ .Values.monitoring.exporter.port }}
23+
targetPort: {{ .Values.monitoring.exporter.port }}
24+
{{- if and (eq .Values.monitoring.exporter.service.type "NodePort") .Values.monitoring.exporter.service.nodePort }}
25+
nodePort: {{ .Values.monitoring.exporter.service.nodePort }}
26+
{{- end }}
27+
{{- end }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- if eq (include "seleniumGrid.monitoring.enabled" $) "true" }}
2+
apiVersion: v1
3+
kind: Secret
4+
metadata:
5+
name: {{ template "seleniumGrid.monitoring.exporter.fullname" $ }}
6+
namespace: {{ .Release.Namespace }}
7+
annotations:
8+
{{- with .Values.monitoring.annotations }}
9+
{{- toYaml . | nindent 4 }}
10+
{{- end }}
11+
labels:
12+
{{- include "seleniumGrid.commonLabels" $ | nindent 4 }}
13+
{{- with .Values.customLabels }}
14+
{{- toYaml . | nindent 4 }}
15+
{{- end }}
16+
type: Opaque
17+
data:
18+
{{- $key := include "seleniumGrid.monitoring.scrape.key" $ -}}
19+
{{- $value := tpl $.Values.monitoring.additionalScrapeConfigs.value $ -}}
20+
{{- if empty $value -}}
21+
{{- range $path, $_ := .Files.Glob "configs/scrape/*.yaml" }}
22+
{{ $key }}: {{ tpl ($.Files.Get $path) $ | b64enc | quote }}
23+
{{- end }}
24+
{{- else }}
25+
{{ $key }}: {{ $value | b64enc | quote }}
26+
{{- end -}}
27+
{{- end }}

Diff for: charts/selenium-grid/templates/patch-keda/patch-keda-objects-job.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ spec:
3434
args:
3535
- |
3636
echo "Cleaning up ScaledObjects, ScaledJobs and HPAs for {{ .Release.Name }} when upgrading or disabling autoscaling."
37-
kubectl patch ScaledObjects,ScaledJobs -n {{ .Release.Namespace }} -l component.autoscaling={{ .Release.Name }} -p '{"metadata":{"finalizers":null}}' || true ;
38-
kubectl delete ScaledObjects,ScaledJobs -n {{ .Release.Namespace }} -l component.autoscaling={{ .Release.Name }} --wait || true ;
37+
kubectl get ScaledObjects,ScaledJobs,TriggerAuthentication -n {{ .Release.Namespace }} -l component.autoscaling={{ .Release.Name }} -o=json | jq '.metadata.finalizers = null' | kubectl apply -f - || true ;
38+
kubectl delete ScaledObjects,ScaledJobs,TriggerAuthentication -n {{ .Release.Namespace }} -l component.autoscaling={{ .Release.Name }} --wait || true ;
3939
kubectl delete hpa -n {{ .Release.Namespace }} -l component.autoscaling={{ .Release.Name }} --wait || true ;
4040
{{- with $.Values.autoscaling.patchObjectFinalizers.resources }}
4141
resources: {{ toYaml . | nindent 12 }}

Diff for: charts/selenium-grid/templates/trigger-auth.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ metadata:
99
{{- toYaml . | nindent 4 }}
1010
{{- end }}
1111
labels:
12+
app: {{ template "seleniumGrid.autoscaling.authenticationRef.fullname" $ }}
13+
app.kubernetes.io/name: {{ template "seleniumGrid.autoscaling.authenticationRef.fullname" $ }}
1214
{{- include "seleniumGrid.commonLabels" $ | nindent 4 }}
1315
{{- include "seleniumGrid.autoscalingLabels" $ | nindent 4 }}
1416
spec:

Diff for: charts/selenium-grid/values.yaml

+40-4
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ rbacRole:
153153
resources:
154154
- scaledobjects
155155
verbs: [get, list, patch, update, delete]
156+
- apiGroups:
157+
- keda.sh
158+
resources:
159+
- triggerauthentication
160+
verbs: [get, list, patch, update, delete]
156161
- apiGroups:
157162
- autoscaling
158163
resources:
@@ -791,6 +796,31 @@ tracing:
791796
monitoring:
792797
enabled: false
793798
enabledWithExistingAgent: false
799+
exporter:
800+
nameOverride: ""
801+
imageRegistry: "ricardbejarano"
802+
imageName: "graphql_exporter"
803+
imageTag: "latest"
804+
# -- Custom pull secret for container in patch job
805+
imagePullSecret: ""
806+
annotations: {}
807+
port: 9199
808+
service:
809+
# -- Create a service for exporter
810+
enabled: true
811+
# -- Service type
812+
type: ClusterIP
813+
# -- Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer)
814+
loadBalancerIP: ""
815+
# -- Node port for service
816+
nodePort: 30199
817+
# -- Annotations for exporter service
818+
annotations: {}
819+
replicas: 1
820+
additionalScrapeConfigs:
821+
key: ""
822+
value: ""
823+
annotations: {}
794824

795825
# Keda scaled object configuration
796826
autoscaling:
@@ -829,11 +859,11 @@ autoscaling:
829859
# -- Define resources for container in patch job
830860
resources:
831861
requests:
832-
cpu: 10m
833-
memory: 10Mi
862+
cpu: 100m
863+
memory: 200Mi
834864
limits:
835-
cpu: 50m
836-
memory: 50Mi
865+
cpu: 200m
866+
memory: 500Mi
837867
# -- Options for KEDA scaled resources (keep only common options used for both ScaledJob and ScaledObject)
838868
scaledOptions:
839869
# -- Minimum number of replicas
@@ -1581,6 +1611,12 @@ ingress-nginx:
15811611
kube-prometheus-stack:
15821612
# enabled: false
15831613
cleanPrometheusOperatorObjectNames: true
1614+
prometheus:
1615+
prometheusSpec:
1616+
additionalConfig:
1617+
additionalScrapeConfigs:
1618+
name: '{{ template "seleniumGrid.monitoring.exporter.fullname" $ }}'
1619+
key: '{{ template "seleniumGrid.monitoring.scrape.key" $ }}'
15841620

15851621
# -- Configuration for dependency chart jaeger
15861622
jaeger:

0 commit comments

Comments
 (0)