Java “Hello world” Microservice with Vert.X, Docker and Kubernetes

This tutorial is a step by step guide to create and deploy Java “Hello world” Microservice with Vert.X, Docker and and Kubernetes in your local laptop.

Image : http://sillyconfusion.com

This is what we are going to do:

  • Develop “Hello world” microservice using Maven, VertX and IntelliJ locally in my laptop
  • Create three VM’s (Dev, Docker registry and MiniKube)
  • Create a docker image of the microservice in Dev environment
  • Configure docker client in Dev environment with private docker registry
  • Push the docker image to private docker registry
  • Configure MiniKube to pull images from private registry
  • Deploy microservice in MiniKube
  • Monitor the deployment using Kubernetes dashboard

Introduction

At present, the traditional paradigm of monolithic application where all the business logic of the software application is bundled and deployed as a single object is gradually replaced by the Microservices architecture.

Monolithic Application

Design of a monolithic application

Microservice Architecture

A microservices is a self sustained piece of software which encapsulates a minimum set of business requirements to facilitate below design principles.

  • Highly maintainable and testable
  • Loosely coupled with other services
  • Independently deployable/up-gradable
  • Capable of being developed by a small team
Microservice Design

Interestingly, Henry Ford was using the principles of work specialization and dividend of work in his production process by introducing the convener belt technology and in my opinion, Microservies are the replication of it in the world of software development.

Microservices — Ford T Model

Since the goal of this tutorial is to focus more on the management aspects of a large scale application, I would suggest you to refer this document to understand the Microservice architecture.

But the operational complexity increases when there are hundreds of microservices working together in a single business application.

Related image
Source : hackernoon.com

This is where Docker and Kubernetes comes into action. Docker is most popular containerization framework.

Let’s understand the technology stack first.

Docker

Docker architecture

Docker uses a client-server architecture. The Docker client talks to the Docker daemon, which does the heavy lifting of building, running, and distributing your Docker containers. The Docker client and daemon can run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate using a REST API, over UNIX sockets or a network interface.

Docker Desktop vs Docker Toolbox

There is a bit difference between docker desktop and docker tookbox. Please refer below article for more details. I am using Docker Desktop for Mac in this tutorial.

https://docs.docker.com/docker-for-mac/docker-toolbox/

Docker Machine

Docker Machine is a tool that lets you install Docker Engine on virtual hosts, and manage the hosts with docker-machine commands. You can use Machine to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or Digital Ocean.

Boot2docker

Boot2Docker is a lightweight Linux distribution made specifically to run Docker containers. It runs completely from RAM, is a ~45MB download and boots quickly.

We will be using docker machine to create and manage our boot2docker VM’s. By using Docker, a microservice can be containerized into a self contained docker image with all the related dependencies. Thereafter, one or many such containers can be deployed in a single operating system (VM or a physical OS). In this tutorial, we will be creating our own private docker registry to deploy the image of the microservice which will be then fetched and deployed by Kubernetes orchestration engine.

Kubernetes

Kubernetes is a portable, extensible open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available.

Kubernetes Architecture

Vert.X

Vert.x is defined as “a toolkit for building reactive applications on the JVM” It is an event driven, polygot, JVM based microservices framework backed by Eclipse.

Software Installation

Let’s install below list of software to develop and deploy our microservice.

  • Oracle VirtualBox — To create VM’s
  • Docker
  • MiniKube — The developer version of Kubernetes
  • Kubectl — CLI to talk with Minikube
  • JDK8
  • Apache Maven

Install and Configure

Install Oracle VirtualBox

Download & Install Oracle VirtualBox for Mac — https://www.virtualbox.org/

VirtualBox

Install Docker

Download & install Docker for Mac — https://hub.docker.com/editions/community/docker-ce-desktop-mac

Both Docker engine and Docker machine will be installed with the above setup.

VM setup

We will be crating 3 VM’s as follow.

  • Dev VM — development environment to creating docker images
  • Docker Registry VM — the private docker registry
  • Kubernetes VM — Minikube installation
VM setup

We will be using docker machine ( installed in my laptop) to create the VM’s in VirtualBox. Please make sure that VirtualBox is up and running.

Creation of VM’s using Docker Machine

Creating registry VM

//below command will create a new VM with the name of registry
docker-machine create -d virtualbox registry
registry VM
registry VM created
//creating a directory in registry to hold docker images
//the ssh command is used to logged into the VM
docker-machine ssh registry "mkdir ~/data"

Now we have a VM with docker installed and the next step is to point the docker CLI in local laptop to docker engine in newly created registry machine.

//change docker cli env variables to point to registry VM docker //engine
eval $(docker-machine env registry)

You can check the env variables using below command.

env | grep DOCKER
docker CLI is pointed to registry machine

Now we need to pull docker registry server image from docker central repository into our registry VM to create a private docker registry. Docker registry server itself is a docker image and it is hosted in central docker registry in cloud (https://hub.docker.com).

//first part of the -p argument is the machine port and 
//the second part is the container port
// -v argument is used to mount the data folder to image storage,
// more : https://docs.docker.com/registry/deploying/
//https://docs.docker.com/storage/volumes/
//last parameter is the name of the registry image

docker run -d -p 80:5000 --restart=always --name registry -v /home/docker/data:/var/lib/registry registry:2
pull registry image from docker central repo
//check the status of docker registry server
docker ps
status of the registry server
//check the IP of the registry server
docker-machine ip registry
registry server IP
//Assign registry server IP to a variable which will be used later
REG_IP=`docker-machine ip registry`
//in my case REG_IP=192.168.99.105
Remember registry server IP

OK, now our private docker registry is up and running. The next step is to create the dev environment.

Creating dev VM

//below command will create a new VM with the name of dev
docker-machine create -d virtualbox dev
creating dev VM
both registry and dev VM’s in VirtualBox

The docker CLI in dev machine should be pointed to registry server to push docker images so that Kubernetes can download those images seamlessly.

image distribution

The registry configuration can be found in /var/lib/boot2docker/profile in dev environment. We need to open it append EXTRA_ARG parameter to this file.

EXTRA_ARGS="--insecure-registry [registry server ip:registry server port]"
Screenshot of the command
//login to dev environment
docker-machine ssh dev
sudo vi /var/lib/boot2docker/profile
//save the file and exit from the VM and restart the VM
exit
docker-machine restart dev
edit boot2docker profile
restart VM

Since the IP of the dev env can change after restart, we need to point docker CLI in local laptop to dev env again.

//set docker CLI to dev env a
eval $(docker-machine env dev)

We can check if everything is working as expected by pushing a pre-created hello-world docker image from dev env to registry server as below.

//pull hello-world docker image from cerntral docker repo 
docker pull hello-world
//tag the image
//refer https://docs.docker.com/engine/reference/commandline/tag/
docker tag hello-world $REG_IP:80/hello-world
//push the image to registry
docker push $REG_IP:80/hello-world
testing the setup

The images in our private registry can be viewed by navigating to registry server web interface.

images in registry server

Let’s deploy and configure our single node Kubernetes cluster.

Install Minikube

Minikube is a tool that makes it easy to run Kubernetes locally. Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.

Installation instructions — https://kubernetes.io/docs/tasks/tools/install-minikube/

Once installed, a new VM will be created in VirtualBox and we now have three VM’s including dev and register.

//Start the cluster and point it to private docker registry server
minikube start --vm-driver="virtualbox" --insecure-registry="$REG_IP":80
start minikube
minikube in VirtualBox
//check the status of minikube
minikube status

Kubectl

The Kubernetes command-line tool, kubectl, allows you to run commands against Kubernetes clusters. You can use kubectl to deploy applications, inspect and manage cluster resources, and view logs.

Installation instructions — https://kubernetes.io/docs/tasks/tools/install-kubectl/

We will be using kubectl to deploy our hello-world microservice later.

//check kubectl is configured properly
kubectl get cs

Microservice Development

Let’s write our microservice using Vert.X toolkit.

The source code can be found here.

https://gitlab.com/email.thusharaj/vertx-hello-world/tree/develop

Make sure that IntelliJ IDE is configured with Apache maven.

In the pom.xml file Vert.X has been added as a maven dependency.

<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.7.0</version>
</dependency>
</dependencies>

In VertX, a simple service can be created by extending AbstractVerticle class as below. When you run this class, anew HTTP server will be created in port 8080.

package io.vertx.kube;

import io.vertx.core.AbstractVerticle;

public class HelloVerticle extends AbstractVerticle {

@Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(request -> {
request.response().end("Hello Java world !");
}).listen(8080);
}
}
HelloVerticle
mvn install

It’s time to run and invoke our microservice using IntelliJ IDE.

https://stackoverflow.com/questions/32205477/how-to-start-vert-x-server-from-intellij-idea

Run microservice
test microservice in browser

We need to create a executable jar file with all the dependencies (a flat jar) to run this microservice in command line. The same jar file will be used to create the docker image. The maven-shade-plugin can is used to create the flat jar as below.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.vertx.core.Launcher</Main-Class>
<Main-Verticle>io.vertx.kube.HelloVerticle</Main-Verticle>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

The flat jar can me created by running maven install command as below.

creating executable jar using maven shade plugin

Jar fill will be created in below directory.

flat jar location

Navigate to target folder from your terminal and run below command to start the microservice.

java -jar vertx-kube-example-1.1.jar
running microservice from command line

It’s running, and you can check it from the browser.

testing microservice in browser

Let’s create a docker image from the jar file of this microservice. First we need to create a Dockerfile to define the docker image definition. A new directory structure has been created and the jar file has been copied as below.

Dockerfile directory structure

Create the Dockerfile and copy below content to it.

Refer : https://vertx.io/docs/vertx-docker/

# Extend vert.x base image
FROM vertx/vertx3

ENV VERTICLE_JAR vertx-kube-example-1.1.jar
ENV VERTICLE_HOME verticles

EXPOSE 8080

# Copy the jar file into a container folder
COPY $VERTICLE_JAR $VERTICLE_HOME/

WORKDIR
.

# Launch the verticle using 'java -jar verticles/vertx-kube-example-1.1.jar' command
ENTRYPOINT ["sh", "-c","java -jar $VERTICLE_HOME/$VERTICLE_JAR"]

Navigate to deploy directory and type below command to create the docker image.

//refer https://docs.docker.com/engine/reference/commandline/build/
//the . param specified the location of the Dockerfile (current directory)
//the -t param is used to tag the image
docker build . -t hello/vertx
build image
//login to dev machine and verify image creation
docker-machine ssh dev
docker image ls
verify image
//run the image
docker run -t -i -p 8080:8080 hello/vertx
run image

Get the IP of the dev machine and check the verify microservice by navigating to the URL from browser.

get the IP of the dev machine
microservice is running in docker container

Note that we haven’t installed Java in the dev machine, but still the service is running. This is the power of docker.

Tag and push the image into service registry.

//tag the image
docker tag hello/vertx $REG_IP:80/hello/vertx
//push the image
docker push $REG_IP:80/hello/vertx
push the image to registry
verify the image in registry

Now, we need to instruct minikube to pull this image from the registry and expose it as a Kubernetes service.

You can understand Kubernetes deployment and services by reading below article.

https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-deployment-tutorial-example-yaml.html

//point docker CLI to minikube VM
eval $(docker-machine env minikube)
//pull the image 
docker pull $REG_IP:80/hello/vertx
//run it on minikube (as a pod)
kubectl run hello-vertx --image=$REG_IP:80/hello/vertx
//expose it as a service, service defines the end-point which should //be used to interact with the deployment.
kubectl expose deployment hello-vertx --port=8080 --type=NodePort
Expose the deployment as a service

Kubernetes dashboard

Kubernetes comes with a nice dashboard and it can be started as follow.

minikube dashboard
minikube dashboard
Kubernetes dashboard

Yeeeeee, we did it.

Note : We haven’t discuss about Deployments, services, replicas, different port types and yaml definitions in this tutorial.

Conclusion

Kubernetes, Docker and Vert.X eco-system not only contribute to developer productivity, but also enables organizations to leverage the benefits of microservices architecture in large scale applications.

References

https://thenewstack.io/tutorial-configuring-ultimate-development-environment-kubernetes/

https://coreos.com/tectonic/docs/latest/tutorials/kubernetes/configure-kubectl.html

https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/

http://escoffier.me/vertx-hol/

I’ll will be sharing more articles on future so don’t forget to follow, clap and comment. Thanks for reading.

Please feel free to contact me on:

Email : email.thusharaj[at]gmail.com

Linkedin : https://www.linkedin.com/in/thusharaj/