How to make use of Spring Boot for Microservices, Docker and Kubernetes

How to make use of Spring Boot  for Microservices, Docker and Kubernetes thumbnail
13K
By Sravan Cynixit 05 May, 2020

This article gives you an overview of building a few microservices using a spring boot, docker, and then deploy them into Kubernetes. So, let's start our Spring boot Docker Kubernetes workshop.

First you need to start with identifying a problem statement. Let's say you need to develop a framework for handling orders. Before starting to deploy let us see the prerequisites.

Pre-requisites

You need to plan a production environment to be able to deploy and test our sample microservices. You will realize that in the following steps:

  • Initially you require one Kubernetes (Minikube) or Openshift (Minishift) node cluster instance running on your local computer. You should start it and expose the embedded Docker client that both have. The detailed instructions for Minishift can be found in my Quick Guide for using OpenShift to deploy Java applications
  • Spring boot Cloud Kubernetes includes access to the Kubernetes API for a list of addresses to be obtained for pods running for a single operation.

Spring Boot Docker workshop

Now let us start deploying Spring boot-microservices with Kubernetes and docker workshop by these following steps.

Domains Identification

The first step would be to identify what domains are needed, so simplicity implies that you need the following domains.

  • Orders
  • Goods
  • Customers or Users
  • Shopping Cart

Now that you know what you are creating, let's start developing. In this workshop, you'd use the following

  • Spring boot for microservices
  • Postgres for Database
  • Gradle to build Docker

First Microservice containers: Products

Let's build our first product micro-service, you'll call it product service, this will contain product details.

Step 1: Use spring initializer to set up spring boot operation.

Go to https:/start.spring.io/ and build a gradle project with Java and Spring boot 2.1.0 and provide the following values.

group Id:  productService 
Dependencies: Server, Jpa, postgresQL 

Select generate project and download the zipped file. Creates a new "order management system" tab. Unzip the file and copy its contents into this new directory in a folder.

Import your favorite IDE into the project and you're good to go. Test if the configuration works fine by running the project on a terminal:

1.	/gradlew build 

Configure the data source by giving the Database credentials and their uri. In the next move let us do this.

Step 2: Database setup

You need a database to hold the product details for the service. You need two things for this:

  • A running postgres database
  • Configure its information in spring

Let's build a local postgres database first. To have a local postgres Server running you can use a docker file. You need dockers in our system to have a postgres database server running as the docker image. Once in your computer the docker is mounted. Pull a picture of the new postgres and run it in your local. You will also create a username and password database that will be used.

Start a postgres server in your local port 5432 and initialize an empty DB 'postgres db' with username 'dbuser' and password 'password.' When the database is up and running, our spring boot program will now be configured to the datasource. One of the ways to identify data source URL and database credentials in the application.properties file, and maybe the simplest one with a spring boot. Spring boot will use these credentials to auto-configure the source of data.

Open the project application.properties file and add the following code.

spring.datasource.url=jdbc:postgresql://localhost:5432/products_db
spring.datasource.username=dbuser
spring.datasource.password=password
spring.jpa.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect	

Design: 1./gradle build

If successful then the build will pass this time.

Run: 1 /gradlew bootRun

Now you're going to have an application running at: http:/localhost:8080/ But since you haven't introduced any service it's going to give a 404. Let's add some code to get it running.

NOTE: this error can occur if you are using postgres version: 1 java.sql.SQLFeatureNotSupportedExceptionMethod org.postgresql.jdbc.PgConnection.createClob

This exception arises since Atomikos-supported JPA (Hibernate) attempts to check the Spring boot SQL Kubernetes. JDBC driver does not enforce this feature so the driver throws an unimportant exception. To correct this,

add 1 spring.jpa.properties.hibernate.jdbc.lob.non contextual creation = true to your application.properties file: 1 spring.jpa.properties.hibernate.jdbc.lob.non contextual creation = true

Step 3: Add code to product service

Create a package with the name: "domain" within the package and create a new Java class "Product" with attributes.

 id
name
description
sku

You would use Lombok to add constructors, getter, setter, and bean builder methods. To use lombok attach its dependency to build.gradle file.

compileOnly 'org.projectlombok:Lombok

Add the annotations to the class 'Product' @Entity

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class Product {
   @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String description;
    private String sku;
}

  • @Entity informs JPA spring boot to handle this class as an entity, and the database persists.
  • @Builder – this lmobok annotation adds the builder method for creating objects using the builder pattern to our class.
  • @AllArgsConstructor – this lmobok annotation adds a constructor of all arguments to the class, this method is required by Builder.
  • @NoArgsConstructor – this lmobok annotation adds a default builder to the class, JPA requires the builder to get the entities.
  • @Getter – this lombok plugin adds getters to all class fields, this is necessary to collect individual product attributes, and Jackson also uses this to serialize / deserialize the fields.

And to build this table in the database, you need to set auto-ddl as true in jpa hibernate. To do this, add the following line to the application.properties file.

spring.jpa.hibernate.ddl-auto=create

You must add to the field I d: @GeneratedValue and @Id, to auto generate value for the Id while creating a new table entry.

Connect Controller

Create a handler and serialize / deserialize the request using Jackson to enforce visibility web services. Make a package with the name: "controller" within the package, and create a new "ProductController" Java class within it.

Annotate the "@RestController" class to expand this interface to a Servlet that exposes the web services. Creating endpoints with the annotation @GetMapping.

@RestController
public class ProductController {
  @GetMapping("/products")
    public List getProducts() {
        return Collections.EMPTY_LIST;
    }

 @PostMapping("/products")
    public Product save(@RequestBody Product product) {
        return null;
    }
}

Make a package with the name: "repository" inside the package and create a new "ProductRepository" interface inside it.

public interface ProductRepository extends JpaRepository {
}
@RestController
public class ProductController {
 private ProductRepository productRepository;
  @Autowired
    public ProductController(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
  @GetMapping("/products")
    public List getProducts() {
        return productRepository.findAll();
    }
    @PostMapping("/products")
    public Product save(@RequestBody Product product) {
        return productRepository.save(product);
    }
}

Dockerise the application in spring boot

Create a file called "dockerFile" in the application's root folder and add the following content to it.

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EXPOSE 8080

Build:

Docker build

Run

Docker run- p 8080:8080 [image-id]

This should start a local host service:8080

Send this request to build a product using a postman or any other similar tool. http:/localhost:8080/products. Header: Application Content-Type / json

{
"name" : "Nike shoes",
"description" : "mens shoes size 10",
"sku" : "1234asc"
}

Spring boot micro services with Kubernetes

Managing these spring boot microservices and their multiple containers may become a bit difficult. Especially in terms of resource scalability, observability, protection, monitoring and management. Therefore we will use Kubernetes for our orchestration of containers.

You could either use a local Kube cluster in the laptop, or use a cloud service such as AWS / Azure / GCP, to get started.

Local Kube Cluster:

We can use Minikube or Docker for Desktop to set up a cluster of local cubes. To mount them on your laptop or device, follow their respective documentations. We will use Docker for Desktop on Mac so if you are using the same follow the steps to set it up.

Using Amazon Elastic Kubernetes Server (EKS):

You can also set up an EKS cluster to deploy the applications, which would include an AWS account (https:/aws.amazon.com/).

Once you have logged into AWS, go to EKS to build a Cluster. For cluster configuration, read this report.

Kubectl:

KubeCtl is a command line interface designed to run commands against clusters in Kubernetes. If you are using Docker for Desktop, the link to the local Kubernetes server is already included and configured, otherwise use this guide to set up KubeCtl on your laptop.

Kubectl requires a kubeconfig file if it is to locate and navigate a Kubernetes cluster. By default, kubectl is set to: 1~/.kube / config.

Using this documentation to set up kubeconfig to verify that kubectl is properly configured by having the cluster state: 1 kubectl cluster-info for cluster management in EKS.

Deploying Applications in the spring boot Kube cluster:

Now that we have successfully created a kube cluster and configured kubectl to manage and deploy into that cluster, we are ready to deploy our applications to it.

You can use these micro services to deploy into the kube cluster. If we use local kube cluster Docker for desktop or MiniKube., You can deploy to the cluster using the local docker file

You need to set a property called "imagePullPolicy" to "Never" in our deployment specification for local images to work. For EKS you will need the image to be in a registry, so we can now use the public repo docker hub so we don't have to think about registry authentication. If we have to use Amazon Elastic Container Registry. You will need to grant the instances running the nodes in the cluster ECR pull permissions for convenience.

Build local image

You will build the docker image in our spring boot micro services system to deploy the application in local kube cluster. Go to productService's root folder and run the command docker build.

docker build -t productservice.

This generates a local picture with "productservice" tag. Check that running this picture works fine.

Docker run -p 8001:8001 Product Service: latest

This service needs access to a local Postgres Database server, therefore it does not start. To be fast, let's make a quick change to the application and use a DB (H2) in memory.

Make the following changes to build.gradle:

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
    runtime("com.h2database:h2:1.3.176")
    compileOnly 'org.projectlombok:lombok:1.18.4'
    testImplementation('org.springframework.boot:spring-boot-starter-test')
}

Rebuild the image this time. Ensure you are cleaning the old tag and run it. To check the endpoints use the procedure in docker employment above. Create and get packages @/products.

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=false

Creating deployment.yaml

You need a deployment description or a pod definition if we simply want to install a pod to deploy the images to kube.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-service-deployment
spec:
  selector:
    matchLabels:
      app: product-service
  replicas: 1
  template:
    metadata:
      labels:
        app: product-service
    spec:
      containers:
      - name: product-app
        image: productservice:latest
        imagePullPolicy: Never
        ports:
        - containerPort: 8001

Save the file above as product-service-deployment.yaml and execute the following command where you save the file.

Apply kubectl -f product-service-deployment.yaml

This will build a Pod in the container cluster running the program. Now this program runs in a pod in the kube cluster and you can allocate an IP address, which can only be accessed from within the cluster. Using this IP address, we would access this pod from within the cluster, but since the pods are transient ,you would need an interface or a protocol to access them through a "service name" that would not alter when the pods are recreated. This "operation" will also serve as a load balancer to hand out requests to the pods.

Build a Kubernetes Service:

Now, in Kubernetes, we must construct a service that you can use to access the pod. You will create a "ClusterIP" type service for this blog that will be accessible from within the cluster.

Build a file with the name product-service.yaml in the same root folder with the following content.

apiVersion: v1
kind: Service
metadata:
  name: product-service
spec:
  selector:
    app: product-service
  ports:
  - port: 8001        	
    targetPort: 8001

To build this service, execute the following command.

kubectl app

You will use something called "kube port-forwarding" to access this service from our laptop using the following command.

kubectl port-forward svc / product-service 8001:8001

Now we can access the service using http:/localhost:8001/products.

So, you now have our spring boot program running in the local cluster of Kubes.

Conclusion

I hope you reach a conclusion about Spring boot microservices with Kubernetes and docker. You can learn more about deploying microservices through spring boot online training.

Share

If You Appreciate This, You Can Consider:

We are thankful for your never ending support.

About The Author

author-image
Iam a Tech Writer

Further Reading on Spring Boot