Spring Boot + Kubernetes Tutorial - Deploy Multiple Microservices Using ClusterIP Service
The REST endpoints exposed by the employee producer microservice we consumed by an external client using nodeport service.

In previous docker tutorial we had created docker images for the employee-producer and employee-consumer microservices.

In this tutorial we will be creating the docker images for both the employee-producer and employee-consumer microservices. Then we will be deploying these images on minikube. Also in another previous tutorial we saw the different service types including clusterip which is used by internal cluster. In this tutorial we will be consuming the employee-producer microservice programatically using another microservice named employee-consumer using clusterip service type.

Implementation
Start Minikubeminikube start --force

To use docker with minikube we will need to switch the docker context to using minikube.
eval $(minikube docker-env)
Deploy employee-producer application to kubernetes pod.
In previous tutorial, we had implemented examples for deploying spring boot applications to docker. In this tutorial series we had covered the basics of docker. We will be taking reference of the spring boot microservices to docker tutorial that we had implemented previously. We will be downloading the spring boot example we had implemented for this tutorial. The docker file used to create the docker image is as follows -From openjdk:8 copy ./target/employee-producer-0.0.1-SNAPSHOT.jar employee-producer-0.0.1-SNAPSHOT.jar CMD ["java","-jar","employee-producer-0.0.1-SNAPSHOT.jar"]Import the spring boot project in eclipse. Build it using maven install, so that we have the jar file inside the target folder.


Next we will build an image with the name employee-producer-kubernetes.
docker image build -t employee-producer-kubernetes .

If now list the available docker images, we can see that the new image has been created.

Next we will run the above image as a container. Also we will be publishing the docker port 8080 to centos port 8080.
docker container run --name producer -p 8080:8080 -d employee-producer-kubernetes

If now list the available docker containers, we can see that the new container has been created.

docker container logs producer

Now using curl we could test the application running in docker as follows-
curl localhost:8080/employee

Pass Docker Image to Kubernetes
The docker image can be passed to minikube in 2 ways--
Local docker image -
Minikube makes use of the locally created docker image. So if we run following commanddocker image ls
We can see the image is present locally. This will be used by minikube to run containers using pods. -
Image from docker hub -
In this case the image will be downloaded from docker hub which is central repository for docker images.
In previous docker tutorials we have already implemented examples for pushing images to docker hub. Using the terminal login to the docker hub account. It will ask for the dockerhub username and password.docker login
-
Next we will push the image named employee-producer-kubernetes to docker hub using the following command.
docker image push employee-producer-kubernetes
But we get the following exception
-
This is because only official docker images can be in the above format with only the name.
All other docker images should be in the format -
owner/docker-image-name So for this we will need to add the owner tag to the existing image that we want to push to docker hub.docker image tag employee-producer-kubernetes javainuse/employee-producer-kubernetes
If we now list the docker images we see two docker images with same id.docker image ls
Create a pod configuration file named employee-producer-pod.yml as follows-apiVersion: v1 kind: Pod metadata: name: employee-producer labels: app: employee-producer spec: containers: - name: boot-jar-container image: javainuse/employee-producer-kubernetes:latest
Deploy the above configuration as follows-kubectl apply -f employee-producer-pod.yml
This creates the pod named employee-producer
If we check the employee-producer pod logs, we can see that the application has started.
Create a new service of type cluserip to expose the employee-producer pod to kubernetes internal applications.
The ClusterIP service configuration to expose the employee producer microservice internally will be as follows-apiVersion: v1 kind: Service metadata: name: employee-producer-service spec: selector: app: boot-jar ports: - protocol: TCP port: 80 targetPort: 8080 type: ClusterIP
This service file has the same selector tag as the label tag in pod configuration file. Deploy the service as follows-kubectl apply -f clusterip-service.yml
This creates the service named employee-producer-service using which other internal applications can access the employee-producer pod.Create and push the employee-producer image to dockerhub.
As we do not have the employee-consumer image in repository in dockerhub we will need to create and push the image to dockerhub. In previous docker tutorial we had created an image for spring boot consumer service. We will be making use of this project to consume the REST endpoints exposed by employee-producer. The project makes use of RestTemplate to call and consume the exposed ClusterIP service using the service name of the deployed clusterip service.package com.javainuse.controllers; import java.io.IOException; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; public class ConsumerControllerClient { public void getEmployee() throws RestClientException, IOException { String baseUrl = "http://employee-producer-service:8080/employee"; RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response=null; try{ response=restTemplate.exchange(baseUrl, HttpMethod.GET, getHeaders(),String.class); }catch (Exception ex) { System.out.println(ex); } System.out.println(response.getBody()); } private static HttpEntity<?> getHeaders() throws IOException { HttpHeaders headers = new HttpHeaders(); headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); return new HttpEntity<>(headers); } }
Also this project has the docker file as follows-From openjdk:8 copy ./target/employee-consumer-0.0.1-SNAPSHOT.jar employee-consumer-0.0.1-SNAPSHOT.jar CMD ["java","-jar","employee-consumer-0.0.1-SNAPSHOT.jar"]
Let us create the image of the employee-consumer project and push it to the docker hub repository.-
Create the docker image as follows-
docker image build -t employee-consumer-kubernetes .
-
Using the terminal login to the docker hub account. It will ask for the dockerhub username and password.
docker login
-
Next we will push the image named employee-producer-kubernetes to docker hub using the following command.
docker image push employee-consumer-kubernetes
But we get the following exception
-
This is because only official docker images can be in the above format with only the name.
All other docker images should be in the format -
owner/docker-image-name So for this we will need to add the owner tag to the existing image that we want to push to docker hub.docker image tag employee-consumer-kubernetes javainuse/employee-consumer-kubernetes
If we now list the docker images we see two docker images with same id.docker image ls
-
We can now push the new image with javainuse tag as follows-
docker image push javainuse/employee-consumer-kubernetes
Deploy employee-consumer image to kubernetes pods
So now we have the employee consumer image in the docker hub repository.
Next we will be creating the pod configuration file named employee-consumer-pod.yml for deployment as follows-apiVersion: v1 kind: Pod metadata: name: employee-consumer labels: app: employee-consumer spec: containers: - name: boot-consumer-container image: javainuse/employee-consumer-kubernetes:latest
Deploy the pod as follows-kubectl apply -f employee-consumer-pod.yml
This creates the pod named employee-producer
If we check the employee-consumer pod logs, we can see that the application has started and also it has programmatically consumed the REST endpoint.
If we check the employee-consumer logs, we can see that it has consumed the REST endpoints exposed by employee-producer. -
Create the docker image as follows-