This reference for version: 1.0.1
+Moon is an enterprise version of Selenoid using Kubernetes to launch browsers.
+1. Getting Started
+1.1. Quick Start Guide
+-
+
-
+
Prerequisites:
+++-
+
-
+
Running Kubernetes cluster
+
+ -
+
+kubectl
client installed and pointing to the cluster
+
+ -
+
-
+
Examples of used YAML and JSON files can be found in Example Configuration Files section.
+
+ -
+
Configure your namespace service account to support Aerokube private registry - replace
+REGISTRY_USERNAME
,REGISTRY_PASSWORD
andREGISTRY_EMAIL
placeholders with your values:++++$ kubectl create secret docker-registry registry.aerokube.com --docker-server=registry.aerokube.com --docker-username=REGISTRY_USERNAME --docker-password=REGISTRY-PASSWORD --docker-email=REGISTRY-EMAIL +$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "registry.aerokube.com"}]}'
+
+
See this Kubernetes documentation section for more details.
+. Copy test quota to quota
directory and initialize browsers configuration:
$ mkdir -p quota +$ touch quota/browsers.json # Add contents to file +$ kubectl create configmap quota --from-file=quota+
-
+
-
+
Start one or more Moon replicas:
+++++$ kubectl create -f moon.yaml
+
+ -
+
Start one or more Moon API replicas:
+++++$ kubectl create -f moon-api.yaml
+
+ -
+
Determine IP addresses or hostnames for
+moon
andmoon-api
services. When testing in Minikube this can be done with the following commands:++++$ minikube service moon --url +http://192.168.99.100:30979
+++++$ minikube service moon-api --url +http://192.168.99.100:41567
+
+ -
+
Run your tests against
+moon
service like you do with regular Selenium:++++http://192.168.99.100:30979/wd/hub
+
+ -
+
Check that
+moon-api
returns statistics:++++$ http://192.168.99.100:41567/status
+++A successful request should return a JSON with browser usage statistics.
+
+
1.2. Cluster Architecture
++
Moon cluster consists of several important components:
+-
+
-
+
Kubernetes configuration map to store browser quota information and various runtime settings.
+
+ -
+
One or more
+moon
application containers. Their main purpose is to start and stop browser containers. These replicas are usually exposed as Kubernetes service available on standard Selenium port4444
. You should run all the tests against this service.
+ -
+
One or more
+moon-api
application containers. This API collects and returns various data about running browsers.moon-api
is usually exposed as Kubernetes service available on HTTP port (e.g.80
or8080
).
+ -
+
Running browser containers. Moon is using exactly the same containers as Selenoid.
+
+
Basic browser startup functionality is completely stateless and does not require any external database to be running.
+1.3. Moon vs Selenoid
+Moon takes all the best practices and features from Selenoid and adds many more:
+-
+
-
+
Unlimited automatic scalability. You always have enough browsers of any desired version available in the cluster. When running the cluster in cloud platforms such as Google Cloud you can adjust settings to automatically scale depending on current load. This allows to combine efficiency with competitive cost.
+
+ -
+
Completely stateless. Selenoid stores in memory information about currently running browser sessions. If for some reason its process crashes - then all running sessions are lost. Moon contrarily has no internal state and can be replicated across datacenters. Browser sessions remain alive even if one or more replicas go down.
+
+ -
+
Uniform load distribution. Load balancers like Ggr provide are using random load distribution across available browser hosts. This makes them inefficient when overall load is above 80% of cluster capacity. Moon delivers exactly uniform distribution working good even under 100% load.
+
+ -
+
Fully graceful. Any maintenance operations with the cluster do not interrupt running browser sessions. Every cluster component shuts down gracefully.
+
+
1.4. Early Access Program
+Although already supporting most of the features Moon is a work in progress. If you are interested to play with it in your Kubernetes cluster - contact us by email: support@aerokube.com and we’ll send you credentials for our registry where compiled binaries reside.
+2. Configuration
+2.1. Configuring Available Browsers
+-
+
-
+
Moon is using exactly the same JSON format as Selenoid. An example file can be found in Example Configuration Files section. Because everything in Kubernetes is being run in containers - you cannot specify path to webdriver binary, only container with browser. To be available across the cluster all configuration data is stored in ConfigMap.
+
+ -
+
Moon supports multiple users, so you need to create one file for each user named
+<username>.json
. For example for usertest
to work properly you should createtest.json
file.
+ -
+
All JSON files should be stored in the same directory because in that case you can update configuration with just one command.
+
+
2.1.1. Updating Browsers List
+To add or remove browsers:
+-
+
-
+
Having configuration files stored in directory update Moon configuration:
+++++$ kubectl update configmap quota --from-file=quota
+
+ -
+
Gracefully restart Moon service:
+++++$ kubectl update -f moon.yaml
+
+
All running user sessions will continue to work without any interruption.
+2.2. CLI Flags
+These flags should be specified in Kubernetes YAML files when starting the cluster.
+2.2.1. Moon Flags
+The following flags are supported by moon
:
-grace-period duration
+ graceful shutdown (default 30s)
+ -guest-user string
+ guest quota user name (default "browsers")
+ -listen string
+ address to bind (default ":4444")
+ -namespace string
+ namespace (default "default")
+ -quota-dir string
+ quota directory (default "quota")
+ -session-attempt-timeout duration
+ new session attempt timeout (default 30s)
+Appendix A: Example Configuration Files
+browsers.json
file contents{
+ "firefox": {
+ "default": "55.0",
+ "versions": {
+ "55.0": {
+ "image": "selenoid/vnc:firefox_55.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "54.0": {
+ "image": "selenoid/vnc:firefox_54.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "53.0": {
+ "image": "selenoid/vnc:firefox_53.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "52.0": {
+ "image": "selenoid/vnc:firefox_52.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "51.0": {
+ "image": "selenoid/vnc:firefox_51.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "50.0": {
+ "image": "selenoid/vnc:firefox_50.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "49.0": {
+ "image": "selenoid/vnc:firefox_49.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "48.0": {
+ "image": "selenoid/vnc:firefox_48.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "47.0": {
+ "image": "selenoid/vnc:firefox_47.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "46.0": {
+ "image": "selenoid/vnc:firefox_46.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "45.0": {
+ "image": "selenoid/vnc:firefox_45.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "44.0": {
+ "image": "selenoid/vnc:firefox_44.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "43.0": {
+ "image": "selenoid/vnc:firefox_43.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "42.0": {
+ "image": "selenoid/vnc:firefox_42.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "41.0": {
+ "image": "selenoid/vnc:firefox_41.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "40.0": {
+ "image": "selenoid/vnc:firefox_40.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "39.0": {
+ "image": "selenoid/vnc:firefox_39.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "38.0": {
+ "image": "selenoid/vnc:firefox_38.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "37.0": {
+ "image": "selenoid/vnc:firefox_37.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "36.0": {
+ "image": "selenoid/vnc:firefox_36.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "35.0": {
+ "image": "selenoid/vnc:firefox_35.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "34.0": {
+ "image": "selenoid/vnc:firefox_34.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "33.0": {
+ "image": "selenoid/vnc:firefox_33.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "32.0": {
+ "image": "selenoid/vnc:firefox_32.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "31.0": {
+ "image": "selenoid/vnc:firefox_31.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "30.0": {
+ "image": "selenoid/vnc:firefox_30.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "29.0": {
+ "image": "selenoid/vnc:firefox_29.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "28.0": {
+ "image": "selenoid/vnc:firefox_28.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "27.0": {
+ "image": "selenoid/vnc:firefox_27.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "26.0": {
+ "image": "selenoid/vnc:firefox_26.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "25.0": {
+ "image": "selenoid/vnc:firefox_25.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "24.0": {
+ "image": "selenoid/vnc:firefox_24.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "23.0": {
+ "image": "selenoid/vnc:firefox_23.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "22.0": {
+ "image": "selenoid/vnc:firefox_22.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "21.0": {
+ "image": "selenoid/vnc:firefox_21.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "20.0": {
+ "image": "selenoid/vnc:firefox_20.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "19.0": {
+ "image": "selenoid/vnc:firefox_19.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "18.0": {
+ "image": "selenoid/vnc:firefox_18.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "17.0": {
+ "image": "selenoid/vnc:firefox_17.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "16.0": {
+ "image": "selenoid/vnc:firefox_16.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "15.0": {
+ "image": "selenoid/vnc:firefox_15.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "14.0": {
+ "image": "selenoid/vnc:firefox_14.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "13.0": {
+ "image": "selenoid/vnc:firefox_13.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "12.0": {
+ "image": "selenoid/vnc:firefox_12.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "11.0": {
+ "image": "selenoid/vnc:firefox_11.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "10.0": {
+ "image": "selenoid/vnc:firefox_10.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "9.0": {
+ "image": "selenoid/vnc:firefox_9.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "8.0": {
+ "image": "selenoid/vnc:firefox_8.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "7.0": {
+ "image": "selenoid/vnc:firefox_7.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "6.0": {
+ "image": "selenoid/vnc:firefox_6.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "5.0": {
+ "image": "selenoid/vnc:firefox_5.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "4.0": {
+ "image": "selenoid/vnc:firefox_4.0",
+ "port": "4444",
+ "path": "/wd/hub"
+ },
+ "3.6": {
+ "image": "selenoid/vnc:firefox_3.6",
+ "port": "4444",
+ "path": "/wd/hub"
+ }
+ }
+ },
+ "chrome": {
+ "default": "60.0",
+ "versions": {
+ "60.0": {
+ "image": "selenoid/vnc:chrome_60.0",
+ "port": "4444"
+ },
+ "59.0": {
+ "image": "selenoid/vnc:chrome_59.0",
+ "port": "4444"
+ },
+ "58.0": {
+ "image": "selenoid/vnc:chrome_58.0",
+ "port": "4444"
+ },
+ "57.0": {
+ "image": "selenoid/vnc:chrome_57.0",
+ "port": "4444"
+ },
+ "56.0": {
+ "image": "selenoid/vnc:chrome_56.0",
+ "port": "4444"
+ },
+ "55.0": {
+ "image": "selenoid/vnc:chrome_55.0",
+ "port": "4444"
+ },
+ "54.0": {
+ "image": "selenoid/vnc:chrome_54.0",
+ "port": "4444"
+ },
+ "53.0": {
+ "image": "selenoid/vnc:chrome_53.0",
+ "port": "4444"
+ },
+ "52.0": {
+ "image": "selenoid/vnc:chrome_52.0",
+ "port": "4444"
+ },
+ "51.0": {
+ "image": "selenoid/vnc:chrome_51.0",
+ "port": "4444"
+ },
+ "50.0": {
+ "image": "selenoid/vnc:chrome_50.0",
+ "port": "4444"
+ },
+ "49.0": {
+ "image": "selenoid/vnc:chrome_49.0",
+ "port": "4444"
+ },
+ "48.0": {
+ "image": "selenoid/vnc:chrome_48.0",
+ "port": "4444"
+ }
+ }
+ },
+ "opera": {
+ "default": "47.0",
+ "versions": {
+ "47.0": {
+ "image": "selenoid/vnc:opera_47.0",
+ "port": "4444"
+ },
+ "46.0": {
+ "image": "selenoid/vnc:opera_46.0",
+ "port": "4444"
+ },
+ "45.0": {
+ "image": "selenoid/vnc:opera_45.0",
+ "port": "4444"
+ },
+ "44.0": {
+ "image": "selenoid/vnc:opera_44.0",
+ "port": "4444"
+ },
+ "43.0": {
+ "image": "selenoid/vnc:opera_43.0",
+ "port": "4444"
+ },
+ "42.0": {
+ "image": "selenoid/vnc:opera_42.0",
+ "port": "4444"
+ },
+ "41.0": {
+ "image": "selenoid/vnc:opera_41.0",
+ "port": "4444"
+ },
+ "40.0": {
+ "image": "selenoid/vnc:opera_40.0",
+ "port": "4444"
+ },
+ "39.0": {
+ "image": "selenoid/vnc:opera_39.0",
+ "port": "4444"
+ },
+ "38.0": {
+ "image": "selenoid/vnc:opera_38.0",
+ "port": "4444"
+ },
+ "37.0": {
+ "image": "selenoid/vnc:opera_37.0",
+ "port": "4444"
+ },
+ "36.0": {
+ "image": "selenoid/vnc:opera_36.0",
+ "port": "4444"
+ },
+ "35.0": {
+ "image": "selenoid/vnc:opera_35.0",
+ "port": "4444"
+ },
+ "34.0": {
+ "image": "selenoid/vnc:opera_34.0",
+ "port": "4444"
+ },
+ "33.0": {
+ "image": "selenoid/vnc:opera_33.0",
+ "port": "4444"
+ },
+ "12.1": {
+ "image": "selenoid/vnc:opera_12.1",
+ "port": "4444",
+ "path": "/wd/hub"
+ }
+ }
+ }
+}
+moon.yaml
file contentskind: Service
+apiVersion: v1
+metadata:
+ name: moon
+spec:
+ selector:
+ app: moon
+ ports:
+ - protocol: TCP
+ port: 4444
+ type: NodePort
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+ name: moon
+spec:
+ replicas: 3
+ template:
+ metadata:
+ labels:
+ app: moon
+ spec:
+ containers:
+ - name: moon
+ image: registry.aerokube.com/moon/moon:1.0.1
+ ports:
+ - containerPort: 4444
+ volumeMounts:
+ - name: quota
+ mountPath: /quota
+ volumes:
+ - name: quota
+ configMap:
+ name: quota
+moon-api.yaml
file contentskind: Service
+apiVersion: v1
+metadata:
+ name: moon-api
+spec:
+ selector:
+ app: moon-api
+ ports:
+ - protocol: TCP
+ port: 8080
+ type: NodePort
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+ name: moon-api
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: moon-api
+ spec:
+ containers:
+ - name: moon-api
+ image: registry.aerokube.com/moon/moon-api:1.0.1
+ ports:
+ - containerPort: 8080
+ volumeMounts:
+ - name: quota
+ mountPath: /quota
+ volumes:
+ - name: quota
+ configMap:
+ name: quota
+