Minikube Tutorial 1 ------------------- The idea behind this tutorial is to replicate the steps in the following Google Kubernetes tutorial: https://codelabs.developers.google.com/codelabs/cloud-springboot-kubernetes/#0 but this time on your local computer, using "minikube". Minikube is a a version of kubernetes that emulates a full cluster on your local computer. It and can be used to experiment with kubernetes, test your microservices application, etc. You need to carry out this tutorial on your local machine, as you will be using minikube for Phase 2 of Project 1. First you need to install minikube on your local computer. Follow the instructions here for installation: https://minikube.sigs.k8s.io/docs/start/. Documentation is also available in the same site. The idea now is to follow the same steps as in the Google tutorial mentioned above. In particular, all kubectl commands are available in minikube, with the only change that you have to type "minikube kubectl" instead of just "kubectl". Some slight modifications will be needed in some of the steps, as discussed below. - The first step is to run "minikube start", or "minikube --driver=docker start". This creates the cluster (or actually, an emulation of the cluster) within your machine. Note, the basic version of minikube only allows one cluster, and that too, a single-node cluster. If you run "minikube dashboard" you will get a lot of info in the browser. From within this Dashboard you can do almost everything that can be done via kubectl. - Understanding minikube's docker server An important detail is that minikube's docker server runs inside its own container on your machine. This is distinct from any docker server that may be running directly on your localhost. "minikube ssh" logs you into the shell of this container. If you do "docker images" within the container, you will see the images actually available to minikube. See https://dzone.com/articles/running-local-docker-images-in-kubernetes-1 for all the details of this. [Note 1: It is not at all necessary for you to do "minikube ssh", as you will issue all minikube client commands from your localhost only; your machine acts as the kubernetes command client, while the minikube container acts as the kubernetes (and docker) server. Note 2: From within the minikube shell, if you do "ps", you will only see processes related to the minikube container. However, if you run some process from within the shell, say "yes", and do "ps" from your normal localhost terminal, you will see this process as a separate process. This is evidence that the container process and its child processes are also processes on the host system, but with isolation. The container process and its child processes can see each other via "ps", and they share a common isolated file system, and they all use the same IP address.] Therefore, any docker image available on your localhost machine, such as a gs-spring-boot image that you built, will not be visible inside minikube, and hence cannot be directly deployed. - Creating the deployment: You can attempt to create a deployment under minikube by typing the following in your localhost (which is the minikube client): minikube kubectl -- create deployment hello-java \ --image=gs-spring-boot But due to the issue mentioned above, the image will not be found within minikube's docker server. minikube will then look for the image in standard repositories, and will not find it their either. Therefore, the deployment will fail to get created. If you would like to push a docker image from your localhost to minikube's docker server, you have three choices. The first choice is to push your image onto a standard repository, and then create the deployment as shown above. The second choice is to upload an image from your localhost's docker server to minikube's docker server directly using the command "minikube image load ". This second option is the easiest. The third choice is as follows, and is to be used if you are about to build an image on your localhost from a locally available project using "docker build". First run "eval $(minikube docker-env)" in a terminal in your localhost machine. It will set various shell variables, which will then force the docker commands that you subsequently issue within the same terminal to be sent to minikube's docker server. In other words, it connects your terminal as a docker client to the docker server within minikube. Now cd to the directory that has the code (e.g., ~/your-path/gs-spring-boot/), and type "docker build -t your-name/gs-spring-boot .", and it will build the image directly into the minikube container. Once the image gs-spring-boot is available in minikube's docker server, try creating the deployment again typing the following in your localhost: minikube kubectl -- create deployment hello-java \ --image=gs-spring-boot This time the deployment gets created. However, unexpectedly, it does not run properly. If you go to the Dashboard, you will see an error message that the image gs-spring-boot was not found (even though it is available locally within the container). This appears to happen because minikube goes looking for the image in the standard repositories even though it is available locally. To rectify this, click on the "..." next to the deployment in the Dashboard, choose Edit, and set the option ImagePullPolicy to Never or IfNotPresent (which tells kubernetes to use the local image if the image is not available in its default repositories). In case this does not work (and it does not work for me), another idea is to append a unique tag to the image name, such as ":v0", after you push the image to minikube. This can be done using the command "docker image tag 995e9eed656a gs-spring-boot:v0" within the "minikube ssh" terminal. Then refer to this image name when creating the deployment (you can first delete the old malfunctioning deployment from the Dashboard). This way, any lookup by minikube's docker server on remote repositories fails, hence forcing it to use the local image. - Run the following command to wrap a service around the deployment created above: minikube kubectl -- expose deployment hello-java \ --type=LoadBalancer --port=8080 Then run "minikube tunnel" in a different terminal window (and don't kill this process, let it stay running). Now, in the Dashboard you will see an external IP address for the service (you can also see this using "minikube kubectl -- get services"). Now you can visit http://:8080. Note, if your service is only going to be invoked by other services (i.e, Spring Boot apps) that you are going to run within the same minikube instance (as you will in Tutorial 2 below), you can drop the "--type=LoadBalancer". In this case it will use by default the ClusterIP type, which also provides load balancing. In either case, since the name of the deployment and service as created above is hello-java, the other services running within the minikube instance can access this service using the URL http://hello-java:8080. - Now you can scale the deployment using kubectl or using the Dashboard. Note, if you scale it up, it may scale it down automatically after a while if the load goes down. If you do "ps aux | grep java" immediately after scaling, you will see multiple instances, corresponding to the multiple pods. This proves that the pods are actually running as processes within your machine. If you do "minikube ssh" and then run "ps aux | grep java" within that shell, you will see the same set of pods, but with different PIDs (PID namespaces in action). From your localhost, if you run: while true; do curl http://10.100.229.219:8080/ ; echo; sleep 0.1; done since there are numerous requests coming back to back, the load-balancer is likely to send different requests to different pods. Since the gs-spring-boot service returns the pod's IP address in the HTTP response, it will become obvious to you that different pods satisfy different requests. - You can stop the minikube service using "minikube stop", and re-start it later using "minikube start" as mentioned above. Minikube Tutorial 2 ------------------- This tutorial is not mandatory. You are encouraged to try it out. It contains steps that will be necessary in your Project 1, Phase 2. First start minikube, and deploy hello-java within it as a service as per Tutorial 1 above. Use ClusterIP type for the service. The rest of this tutorial is about deploying another service that will act as a client and invoke the hello-java service. Write another Spring Boot application. The main controller in this application could have code such as the following: InetAddress ip = null; StringBuffer content = new StringBuffer(); try { URL url = new URL("http://hello-java:8080"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); ip = InetAddress.getLocalHost(); con.setRequestMethod("GET"); int status = con.getResponseCode(); Reader streamReader = null; if (status <= 299) { BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); } } catch (Exception e) { return "Internal error " + e + " encountered in server " + ip + " !"; } return "Greetings from Spring Boot running at " + ip + "." + " hello-app service returned the following message: " + content; Now build this application as an image, and deploy it also into minikube just as in Tutorial 1. For this application, wrap the deployment as a LoadBalancer service. Now reach out to this application as an end-user from your browser. It will in turn send requests to hello-java.