{"id":2608,"date":"2020-08-23T07:05:08","date_gmt":"2020-08-23T07:05:08","guid":{"rendered":"http:\/\/www.ruthtech.com\/?p=2608"},"modified":"2020-08-23T08:36:46","modified_gmt":"2020-08-23T08:36:46","slug":"setting-up-selenium-hub-in-kubernetes","status":"publish","type":"post","link":"https:\/\/www.ruthtech.com\/?p=2608","title":{"rendered":"Setting up Selenium Hub in Kubernetes"},"content":{"rendered":"<p><strong>Setting up Selenium Hub in Kubernetes<\/strong><br \/>\nThis tutorial assumes that you can write and set up a basic selenium test automation framework. This tutorial will focus on setting up selenium hub in kubernetes infrastructure, explaining some of the basic terminologies and how to set it up.<\/p>\n<p><strong>Definitions &#8211;<\/strong><\/p>\n<ol>\n<li><strong>Kubernetes<\/strong> &#8211; is an open-source system for automating deployment, scaling, and management of containerized applications<br \/>\nAnother definition that I like is &#8211; k8 is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation.<\/li>\n<li><strong>Cluster<\/strong> &#8211; A Kubernetes cluster consists of a set of worker machines, called nodes, that run containerized applications. Every cluster has at least one worker node.<br \/>\nThe worker node(s) host the Pods that are the components of the application workload. The control plane manages the worker nodes and the Pods in the cluster. As seen in the diagram below:<\/li>\n<\/ol>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-large\" src=\"https:\/\/d33wubrfki0l68.cloudfront.net\/7016517375d10c702489167e704dcb99e570df85\/7bb53\/images\/docs\/components-of-kubernetes.png\" width=\"1500\" height=\"685\" \/><\/p>\n<p><strong>Tools<\/strong> &#8211;<\/p>\n<ol>\n<li><span style=\"color: #008000;\"><a style=\"color: #008000;\" href=\"https:\/\/github.com\/femisimon\/kube-selenium-demo\">GitHub Repo<\/a> <\/span>&#8211;<\/li>\n<li>IDE &#8211; (<span style=\"color: #008000;\"><a style=\"color: #008000;\" href=\"https:\/\/code.visualstudio.com\/download\">VS Code Suggested<\/a><\/span>)<\/li>\n<\/ol>\n<p><strong>Installation<\/strong><br \/>\nIn this tutorial we will be going through how to set up kubernetes on your local machine as well as in cloud &#8211; AWS and GC.<\/p>\n<ol>\n<li><strong>Local environment:<\/strong><br \/>\nInstall VSCode, install the Kubernetes plug and its dependencies and go through the steps below:<\/p>\n<ol>\n<li>Brew &#8211; install here<br \/>\n<em>\/bin\/bash -c &#8220;$(curl -fsSL https:\/\/raw.githubusercontent.com\/Homebrew\/install\/master\/install.sh)&#8221;<\/em><\/li>\n<li>VM: Hyperkit Driver &#8211; Install (Optional)\n<ol>\n<li><em>brew install docker-machine-driver-hyperkit<\/em><\/li>\n<li><em>sudo chown root:wheel ~\/.minikube\/bin\/docker-machine-driver-hyperkit<\/em><\/li>\n<li><em>sudo chmod u+s ~\/.minikube\/bin\/docker-machine-driver-hyperkit<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Minikube &#8211; Installation link\n<ol>\n<li><em>brew install minikube<\/em><\/li>\n<li><em>sudo mv minikube \/usr\/local\/bin<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Kubernetes CLI &#8211;\n<ol>\n<li><em>brew install kubernetes-cli (This is automatically installed with minikube)<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Kubectl Install here (Upgrade)\n<ol>\n<li><em>brew install kubectl<\/em><\/li>\n<li><em>brew install kubectl 1.18.0<\/em><\/li>\n<li><em>chmod +x .\/kubectl<\/em><\/li>\n<li><em>sudo mv .\/kubectl \/usr\/local\/bin\/kubectl<\/em><\/li>\n<li>Verify version &#8211; <em>kubectl version &#8211;client<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Start Cluster\n<ol>\n<li><em>minikube start (will automatically download hyperkit)<\/em><\/li>\n<li><em>minikube dashboard<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Setting up Selenium Hub needed to run test in Kubernetes\n<ol>\n<li>We need to create a deployment app in a deploy.yml file that has all the set up needed to create a selenium-hub. The file contains the following:\n<ol>\n<li><em>The application version &#8211; appVersion<\/em><\/li>\n<li><em>What kind of app we wanna establish &#8211; Deployment<\/em><\/li>\n<li><em>The metadata to identify the pod. In this case we use &#8211; name<\/em><\/li>\n<li>The spec\n<ol>\n<li><em>The spec has a template format, where we need to set up the image that needs to be deployed in the container.<\/em><\/li>\n<li>The name of the container and the port that we want to expose and for selenium we will be using the default &#8211; 4444<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>To deploy a pod\n<ol>\n<li>There are several ways to deploy or start a pod within the namespace of a cluster. We are going to deploy our pods directly from the file. Using the command:<br \/>\n<em>Kubectl create -f<\/em><\/li>\n<li>To get the list of the pods in the cluster, we are going to use the command:<br \/>\n<em>Kubectl get pods<\/em><\/li>\n<li>To get all the information about a particular pod or function, we are going to use the command:<br \/>\n<em>Kubectl describe pod <\/em><\/li>\n<li>You\u2019ll get the pod name from the metadata name tag or from the list provided from <em>\u201ckubectl get pods\u201d<\/em><\/li>\n<\/ol>\n<\/li>\n<li>Set up Service to expose the application\n<ol>\n<li>When the selenium-hub application is deployed, we need a way to expose the 4444 to other nodes that want to connect to the hub.<\/li>\n<li>So we create a service application and name it whatever you like but in this case I named it &#8211; service.yml<\/li>\n<li>The service.yml file contains the following with some explanation of the parameters mean.\n<ol>\n<li>The apiVersion, as the name implies is the apiVersion provided by the Kubernetes team.<\/li>\n<li>What kind of app are we looking to set up; this kind is &#8211; Service<\/li>\n<li>Metadata &#8211; we need a way to identify the pod and within the metadata we have &#8211;\n<ol>\n<li>Name &#8211; The name of the pod.<\/li>\n<li>Label &#8211; We also add a label to identify the application, because the service is an application.<\/li>\n<\/ol>\n<\/li>\n<li>Spec &#8211; We also add the spec to provide more information on the application as well. The Service spec has the following &#8211;\n<ol>\n<li>A selector &#8211; which is used to define the application that we want to expose its port to other services within the namespace or cluster.\n<ol>\n<li>App &#8211; the name of the app that the service needs to select and expose its ports.<\/li>\n<\/ol>\n<\/li>\n<li>Ports &#8211; The application identified in the selector has its ports and the new port(s) that we are going to map it to for other services to use as a point\/port of access\n<ol>\n<li>Port -The original port of the application that the service is exposing its port and in this case its the selenium-hub which is 4444.<\/li>\n<li>nodePort &#8211; we are using nodePort to expose the port of the application by mapping the new port. It is good practice to use ports in the 30000-39999 range.<\/li>\n<li>Nodeport &#8211; We need to tell the service application to use nodeport.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>Create a Replica Controller &#8211;\n<ol>\n<li>We are going to use the replica controller to ensure that we have control over the pods lifecycle. The replica controller helps to ensure that the number of pods we declared and instantiated remains the same. Like in the replica.yml you\u2019ll notice that we declared 2 selenium-chrome to be live and running in the namespace or cluster.<\/li>\n<li>In summary the replica controller will do these things for us &#8211;\n<ol>\n<li>Create the replica controller kind with the number of browser nodes needed to stay alive, running and active.<\/li>\n<li>Connect to the service to provide the bridge between the grid and the individual nodes.<\/li>\n<\/ol>\n<\/li>\n<li>The replica.yml contains the following &#8211;\n<ol>\n<li>apiVersion &#8211; By now you understand what the apiVersion is used for in the yml file.<\/li>\n<li>Kind &#8211; The feature kind here is replica controller and in summary, is used to maintain the lifecycle of pods declared.<\/li>\n<li>Metadata &#8211; because we need to identify the replica controller pod\n<ol>\n<li>Name &#8211; we use the name of the pod to identify the pod via its metadata. The name in our replica.yml file is &#8211; selenium-rep<\/li>\n<\/ol>\n<\/li>\n<li>Spec &#8211; Lets define the specification of the application\n<ol>\n<li>Replicas &#8211; As its name implies, it is used to determine the number of replicas of the pod that is needed to be up and running always.<\/li>\n<\/ol>\n<\/li>\n<li>Selector &#8211; This is used to identify the application or container that needed to be selected for a particular action.\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li>App &#8211; The app in the case is the: selenium-chrome which is defined within the \u201ctemplate\u201d first<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>Please note that the replica controller does not consist of just these parameters, we are only declaring the ones that we need for this topic.<br \/>\nCreate the replica controller kind to determine the number of browser node needed.<br \/>\nConnect to the service to provide the bridge between the grid and the individual nodes<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li><span style=\"font-size: inherit;\">Run tests in the Selenium Hub.<\/span>\n<ol>\n<li><span style=\"font-size: inherit;\">To get the IP &#8211; there are several ways to get the IP, the one I recommend which will also be easier for you to remember is using the kubectl to describe the selenium-hub.<\/span>\n<ol>\n<li><em>Kubectl describe pod selenium-hub<\/em><\/li>\n<li><span style=\"font-size: inherit;\">All the information about the selenium-hub will be rendered. You want to pay attention to the value of the Node &#8211; minikube\/XXX.XX.XX.X<\/span><\/li>\n<li><span style=\"font-size: inherit;\">The IP value will be listed as the value of Node<\/span><\/li>\n<\/ol>\n<\/li>\n<li><span style=\"font-size: inherit;\">Selenium test suite &#8211;<\/span>\n<ol>\n<li><span style=\"font-size: inherit;\">The document assumes that you know how to run selenium tests remotely using the remote function provided by selenium.<\/span><\/li>\n<li>To run tests in the Kubernetes cluster; your remote url needs to be updated with the IP obtained from describing service.yml and the nodePort provided. <em>For example \u21d2 http:\/\/XXX.XX.XX.X:30001\/wd\/hub<\/em><\/li>\n<li><span style=\"font-size: inherit;\">Run your tests with your usual commands.<\/span><\/li>\n<li><span style=\"font-size: inherit;\">TIP &#8211; Write a script to check that the hub\u2019s availability before running test &#8211; <em>http:\/\/XXX.XX.XX.X:30001\/wd\/hub\/status<\/em><\/span><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li><span style=\"font-size: inherit;\">Quick Kubectl commands<\/span>\n<ol>\n<li><em style=\"font-size: inherit;\">Kubectl get pods<\/em><\/li>\n<li><em style=\"font-size: inherit;\">Kubectl create -f <\/em><\/li>\n<li><em style=\"font-size: inherit;\">Kubectl delete pod <\/em><\/li>\n<li><em style=\"font-size: inherit;\">kubectl delete replicationcontroller selenium-rep<\/em><\/li>\n<li><em style=\"font-size: inherit;\">kubectl delete deployment selenium-hub<\/em><\/li>\n<li><em style=\"font-size: inherit;\">kubectl delete svc selenium-srv<\/em><\/li>\n<li><em style=\"font-size: inherit;\">Kubectl describe<\/em><span style=\"font-size: inherit;\"> &lt;function&gt;<\/span>\n<ol>\n<li><span style=\"font-size: inherit;\">Functions can be &#8211; deploy, svc &#8211; kubectl describe svc<\/span><\/li>\n<li><span style=\"font-size: inherit;\">Kubectl describe pod kubectl describe replicationcontroller selenium-rep<\/span><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li><span style=\"font-size: inherit;\">Debugging<\/span>\n<ol>\n<li><span style=\"font-size: inherit;\">Download VNC from Chrome<\/span><\/li>\n<li><span style=\"font-size: inherit;\">Replace POD_NAME with the name of the pod you want to connect to.<\/span><\/li>\n<li><em><span style=\"font-size: inherit;\">kubectl port-forward $POD_NAME 5900:5900<\/span><\/em><\/li>\n<li><span style=\"font-size: inherit;\">Then connect to localhost:5900 with your VNC client using the password &#8220;secret&#8221;<\/span><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li><strong><span style=\"font-size: inherit;\">Cloud Environment &#8211; Coming soon.<\/span><\/strong>\n<ol>\n<li><strong><span style=\"font-size: inherit;\">Amazon EKS &#8211; Managed Kubernetes Service or <\/span><\/strong><\/li>\n<li><strong><span style=\"font-size: inherit;\">Google Kubernetes Engine.<\/span><\/strong><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Setting up Selenium Hub in Kubernetes This tutorial assumes that you can write and set up a basic selenium test [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2616,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[130,139],"tags":[136,145,146,153,155,141,144,154,151,150,156,131,152,137,157,143,142,148,149,147],"_links":{"self":[{"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/posts\/2608"}],"collection":[{"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2608"}],"version-history":[{"count":7,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/posts\/2608\/revisions"}],"predecessor-version":[{"id":2635,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/posts\/2608\/revisions\/2635"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=\/wp\/v2\/media\/2616"}],"wp:attachment":[{"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2608"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2608"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ruthtech.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}