Hazelcast and Springboot on Kubernetes
Hello Everyone, In last post we have seen how to build distributed cache as a spring boot application.
Today we are going to deploy that application to kubernetes.
Why Kubernetes?
Hazelcast is a In-memory data grid solution where that idea is to distribute data across many nodes inside a cluster. Kubernetes is an ideal solution to run such an environment on cloud platform as you can easily scale up and scale down the number of running instances.
Architecture
Now, we want to run such multiple spring boot application on Kubernetes.
Each of spring boot application exposes port 8080 for http access and 5701 Hazelcast cluster members discovery. Each of the hazelcast instace is embedded into spring boot application.
In the above architecture, we have exposed hospital service via 8080 for http access and we have also exposed hazelcast servie for enabling discovery between Hazelcast instances via 5701.
Implmentation
From previous post, will start making changes to the code.
We will have to add kubernetes dependencies. Below is the pom file after changes.
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.rbitcs</groupId><artifactId>doctors</artifactId><version>0.0.1-SNAPSHOT</version><name>doctors</name><description>Spring Boot Application with hazelcast</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast</artifactId></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>spring-data-hazelcast</artifactId><version>2.2.2</version></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast-spring</artifactId></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast-client</artifactId></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast-kubernetes</artifactId><version>1.5.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
Now, we have to disable multicast discovery, which is enabled by default and enable discovery through Kubernetes as below.
@Bean Config config() { Config config = new Config(); config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(false); config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); config.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) .setProperty("namespace", "default") .setProperty("service-name", "hazelcast-service"); return config; }
Next we have to define Doctor service on 5701 as k8s service. This is referred to Doctor Service.
apiVersion: v1
kind: Service
metadata:
name: hazelcast-service
spec:
selector:
app: doctor-service
ports:
- name: hazelcast
port: 5701
type: LoadBalancer
We have to set up kubernetes deployment and service definition. From our architecture we are setting up 3 replicas for our deployment, which are exposed out of continers with 2 ports 8080 and 5701.
Below is the deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: doctor-service
labels:
app: doctor-service
spec:
replicas: 3
selector:
matchLabels:
app: doctor-service
template:
metadata:
labels:
app: doctor-service
spec:
containers:
- name: doctor-service
image: rbitcs/doctor-service
ports:
- name: http
containerPort: 8080
- name: multicast
containerPort: 5701
---
apiVersion: v1
kind: Service
metadata:
name: doctor-service
labels:
app: doctor-service
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: doctor-service
type: NodePort
That’s all with the changes.
Lets run hazelcast on Kubernetes via Minikube
$ minikube start --vm-driver=virtualbox$ skaffold dev
Since we defined 3 replicas, after successful start up we should see three fragment of pods logs printed out by Skaffold
list of services HTTP API is available outside Minikube
The deployment.yaml can be changed as desired state is required. This is how scability can be achieved.
Please take a look at github for complete code.