Service Discovery for Spring Boot App using Kubernetes

Bubu Tripathy
6 min readApr 30, 2023

--

Introduction

As organizations continue to embrace microservices architecture, the need for efficient service discovery becomes more critical. Service discovery is the process of automatically identifying and locating services within a network. In this article, we will explore how to achieve service discovery for a Spring Boot application using Kubernetes.

Prerequisites

  1. Create a Spring Boot Application

2. Create a Docker Image

To deploy your Spring Boot application to Kubernetes, you need to create a Docker image of your application. You can do this by creating a Dockerfile in the root of your project. Here is an example Dockerfile for the book-service:

FROM adoptopenjdk/openjdk11:alpine-jre
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

To build the Docker image, navigate to the root of your project and run the following command:

docker build -t <image-name>:<tag> .

Replace <image-name> and <tag> with the name and tag you want to give to your image.

3. Deploy your application to Kubernetes

To deploy your application to Kubernetes, you need to create a Kubernetes deployment and service. The deployment defines the pods that should be created, while the service exposes your application to other services in the cluster.

Create a deployment by creating a YAML file with the following contents:

apiVersion: apps/v1
kind: Deployment
metadata:
name: book-service
spec:
replicas: 3
selector:
matchLabels:
app: book-service
template:
metadata:
labels:
app: book-service
spec:
containers:
- name: book-service
image: <image-name>:<tag>
ports:
- containerPort: 8080

This YAML file defines a deployment with three replicas. It also specifies that the deployment should create pods with a label of app: book-service and that the container should expose port 8080.

To create the deployment, run the following command:

kubectl apply -f <deployment-file>.yaml

Replace <deployment-file> with the name of the YAML file you created.

What is Service Discovery?

Service discovery is a fundamental concept in a microservices architecture. In a traditional monolithic application, all the services are packaged together, and it is relatively easy to locate and communicate with them. However, in a microservices architecture, each service runs independently, making it challenging to locate and communicate with them.

Service discovery addresses this challenge by providing a way for services to find each other automatically. It allows services to discover the location of other services within a network, making it easier to communicate and interact with them.

The Service Object

In Kubernetes, the Service object is used to represent a set of pods that perform the same function. It provides a stable IP address and DNS name that other services can use to communicate with the pods.

When a service is created, Kubernetes creates an endpoint object that contains the IP addresses of the pods associated with the service. The endpoint object is updated automatically whenever a new pod is added or removed from the service. Here’s an example of how to define a Kubernetes Service object for a Spring Boot application:

apiVersion: v1
kind: Service
metadata:
name: book-service
spec:
selector:
app: book-service
ports:
- name: http
port: 8080
targetPort: 8080

In this example, we are defining a Kubernetes Service object named “book-service”. The selector field specifies the label selector that identifies the set of pods that the service will load balance traffic to. In this case, the label selector is app: book-service, which matches pods with the label app=book-service.

The ports field specifies the ports that the service will listen on. In this case, we are defining a port named "http" that listens on port 8080 and forwards traffic to port 8080 on the pods. Once you have defined the Kubernetes Service object, you can deploy it to your Kubernetes cluster using the kubectl apply command:

kubectl apply -f service.yaml

After the Service object is deployed, you can use its DNS name to communicate with the pods that are associated with the service.

Service DNS

Kubernetes provides a built-in DNS service that allows services to be discovered by their DNS name. Each service is assigned a DNS name that is based on its name and namespace. The DNS name for the service is in the following format:

<service-name>.<namespace>.svc.cluster.local

For example, if you have a service named “my-service” in the “my-namespace” namespace, its DNS name would be “my-service.my-namespace.svc.cluster.local”.

By using the DNS name of a service, other services can communicate with it without having to know its IP address. This makes it easier to scale and manage services in a microservices architecture.

To test the book-service, run the following command:

curl http://book-service.default.svc.cluster.local:8080/books

This command will make a GET request to the book-service to retrieve a list of books.

Load Balancer Integration

Kubernetes also provides integration with load balancers, allowing services to be exposed externally. Load balancers distribute traffic across multiple pods, ensuring that the load is evenly distributed and providing high availability.

To expose a service externally, you can use the LoadBalancer type in the Service object. This creates a load balancer that distributes traffic across the pods associated with the service. Update the book service YAML file:

apiVersion: v1
kind: Service
metadata:
name: book-service
spec:
selector:
app: book-service
ports:
- name: http
port: 8080
targetPort: 8080
type: LoadBalancer

Here, we have added the type: LoadBalancer field to the service YAML file. This will create a new LoadBalancer service that will be responsible for distributing traffic across the pods running the book-service.

Apply the updated service YAML file:

kubectl apply -f <service-file>.yaml

Check the LoadBalancer service:

kubectl get svc book-service

This command will retrieve the details of the book-service LoadBalancer service, including its external IP address.

Test the LoadBalancer service:

curl http://<external-ip>:8080/books

Replace <external-ip> with the external IP address of the LoadBalancer service that you retrieved in step 3. This will make a GET request to the book-service through the LoadBalancer, which will distribute the traffic across the pods running the book-service.

Spring Cloud Kubernetes

Spring Cloud Kubernetes is a framework that provides integration between Spring Boot applications and Kubernetes. It provides several features, including service discovery, configuration management, and load balancing.

To use Spring Cloud Kubernetes for service discovery, we need to add the spring-cloud-starter-kubernetes dependency to our Spring Boot application. This dependency provides the necessary classes and interfaces to interact with the Kubernetes API.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>

Once we have added the dependency, we can use the @LoadBalanced annotation on our RestTemplate beans to enable load balancing and service discovery. The @LoadBalanced annotation adds an interceptor to the RestTemplate that resolves service names using Kubernetes Services.

Here’s an example of a RestTemplate bean with the @LoadBalanced annotation:

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

With this configuration, we can use the RestTemplate to call services using their logical name, rather than their IP address and port. For example, if we have a Service named my-service, we can use the following code to call it:

restTemplate.getForObject("http://my-service/path", String.class);

Spring Cloud Kubernetes also provides support for using Kubernetes ConfigMaps and Secrets to configure Spring Boot applications. This allows us to store configuration data outside of the application code, making it easier to manage and update.

Conclusion

In a Kubernetes environment, service discovery is essential for effective communication between components. Kubernetes Services and Spring Cloud Kubernetes are two ways to implement service discovery in a Spring Boot application. Kubernetes Services provides a simple and flexible approach to service discovery, while Spring Cloud Kubernetes provides additional features such as load balancing and configuration management.

When deciding which approach to use, consider the complexity of your application and the specific requirements for service discovery. If your application is simple and does not require advanced features, Kubernetes Services may be sufficient. However, if your application requires more advanced features or if you are already using Spring Cloud, Spring Cloud Kubernetes may be a better fit.

Thank you for your attention! Happy Learning!

--

--

Bubu Tripathy
Bubu Tripathy

Written by Bubu Tripathy

Senior Software Engineer l Microservices l Cloud Computing l DevOps || LinkedIn:https://www.linkedin.com/in/bubu-tripathy-8682187/

No responses yet