Three months ago I was learning Docker swarm now I’m learning kubernetes as orchestrator this year I’m gonna write about k8s a lot so the idea here is show how to deploy Java Aplications within Docker Containers orchestra them with Kubernetes.

When you run containers you always gonna need a orchestrator in order to be more efficient, faster and continuous delivery and so on that’s the reason why I’ve chosen kubernetes and the true is basically because is the most popular I would say it’s so robust, ambicious, fault-tolerance, scaling, discovery abilities and why not use it, mainly was created at Google and now is hosted by the Cloud Native Computing Foundation(CNCF).

Let’s see the architecture of the “Docker Java Shopfront” application:

Docker Java

Now I will write some concepts which it’s important know.

  • kubectl Kubernetes command-line tool which control the kubernetes cluster manager.
  • labels It’s the way how we can identify pods and be selected we have the freedom of write in JSON or YAML format.
  • Pods is essentially a group of one o more containers we can say it’s a set of one or many containers sharing the same IP, share a filesystem and network namespace. The way how k8s communicate with pods is through kubectl.
  • Services Provide load balancing, naming and discovery to isolate one microservices from another working together with Replications Controller which ensure that containers are working within pods correctly.

Prerequisities:

  • Docker for Mac/Windows/Linux Kubernetes will work with one of the most popular provider containers (Docker).

  • Minikube It’s a tool that run a single-node Kuebernetes test cluster via VM.

  • A github account and Git - The examples(code) of this deployments are hosted in github, using git locally you can clone, fork, commit and so on.

  • Docker hub account - You will need to host your images but it’s up to you because you can use the original source.

  • Java 8 or 9 SDK and Maven(mvn) - We will use Maven(in my case I didn’t install mvn I just runned a container with Maven into a Container, you see the step next) in order to build code and dependency tool that uses Java 8.

Let’s create a service for shopfront

Clone the repository:

$ git clone git@github.com:tuxisma/oreilly-docker-java-shopping.git

$ cd oreilly-docker-java-shopping/shopfront

I loaded the code of shopfront on sublime in order to look into it.

alt text This code is one of them.

Now we gonna build the application using Maven as a result of -we will see a JAR located in the ./target directory.

Here a trick:

I didn’t install Maven but I need to have mvn which means I can run it into a container, just go into shopfront/ and mvn will take the pom.xml file. (Trick share it by yazpik )

docker run -it --rm -v $PWD:/usr/src/mymaven -w /usr/src/mymaven maven  mvn clean install

Now I will create a image from Dockerfile:

FROM openjdk:8-jre
ADD target/shopfront-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8010
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Our container image shuld be created from the openjdk:8-jre, the second line adds the app to the image, the third line specify that our app will be available through port 8010 and the last line specifies the entrypoint which means the command to run when container is initialized.

Let’s build the image:

tuxisma(user on dockerhub)

$ docker build -t tuxisma/djshopfront:1.0 .
Successfully built 87b8c5aa5260
Successfully tagged tuxisma/djshopfront:1.0

Non I will push the image to Docker Hub.

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username:
Password:
Login Succeeded
$
$ docker push tuxisma/djshopfront:1.0
The push refers to a repository [docker.io/tuxisma/djshopfront]
9b19f75e8748: Pushed 
...
cf4ecb492384: Pushed 
1.0: digest: sha256:8a6b459b0210409e67bee29d25bb512344045bd84a262ede80777edfcff3d9a0 size: 2210

Deploying with Kubernetes

Well we have the image of shopfront in Java. Let’s run this image called tuxisma/djshopfront:1.0 using k8s, change the “kubernetes” directory in the root of the project:

$ cd ../kubernetes

We see in the yaml file the version of API(v1), kind of pod , the way of how need to write a yaml file is basically key: value where key is apiVersion and value is v1 and so on.

Basically we have two types of structure in yaml file:

  • Maps

  • Lists

Maps

Usually you can find yamls in this way:

---
apiVersion: v1
kind: Service
metadata:
  name: shopfront
  labels:
    app: shopfront

At the first line we have a separator could be optional but if you want to define multiple structures in the same file use it. Next we have a name(known as key) then a value, pay attention now the key metadata has other two more keys(name, labels) and labels key has another key named app and its value(shopfront). Labels is used to organize and to select subsets of objects, labels are key:value pairs as well.

Be careful with spaces, look onto yaml file notice that metadata key has two more keys as I mentioned both at the same level I will recommend you use two space left to right(see name and labels) ‘cause both belong to metadata or if you want use one space at least, the goal is achieve the indentation as programming language tend to do. Please don’t use tab

Lists

Yaml lists are sequence of objects:

args
  - sleep
  - "1000"
  - message
  - "Bring back Firefly!"

We can see any muber of items in a list which start with dash(-) idented from the parent(args).

And obviusly members of the list can be maps:

 spec:
      containers:
      - name: nginxhttps
        image: tuxisma/djshopfront:1.0
        ports:
        - containerPort: 8010
        livenessProbe:
          httpGet:
            path: /health
            port: 8010
          initialDelaySeconds: 30
          timeoutSeconds: 1

Let’s put the shopfront-service.yaml file together

---
apiVersion: v1
kind: Service
metadata:
  name: shopfront
  labels:
    app: shopfront
spec:
  type: NodePort
  selector:
    app: shopfront
  ports:
  - protocol: TCP
    port: 8010
    name: http

---
apiVersion: v1
kind: ReplicationController
metadata:
  name: shopfront
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: shopfront
    spec:
      containers:
      - name: nginxhttps
        image: tuxisma/djshopfront:1.0
        ports:
        - containerPort: 8010
        livenessProbe:
          httpGet:
            path: /health
            port: 8010
          initialDelaySeconds: 30
          timeoutSeconds: 1

Here we are creating a service named “shopfront” that will route TCP traffic on port 8010 to pods using the label “app:shopfront”. The next structure creates a ReplicationController that says to k8s how many containers should run(one replica) as we have declared as part of the “spec”(specification) labelled as app: shopfront. It’s important specify that the port 8010 application traffic port in our Docker container is open, also we have a livenessProbe(healthcheck) which mean that k8s check if our containerized applications is running correctly and ready to acept traffic.

Now, we need to start minikube in order to deploy this service(shopfront).

$ minikube start --cpus 2 --memory 4096
Starting local Kubernetes v1.7.5 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.

Deploying:

$ kubectl apply -f shopfront-service.yaml
service "shopfront" created
replicationcontroller "shopfront" created

Let’s check all the services within k8s:

$ kubectl get svc
NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
kubernetes   10.0.0.1     <none>        443/TCP          18h
shopfront    10.0.0.216   <nodes>       8010:31208/TCP   12s

Now checking the pods:

$ kubectl get pods
NAME              READY     STATUS              RESTARTS   AGE
shopfront-0w1js   0/1       ContainerCreating   0          18s

As we can see the pod is just creating, what about now:

$ kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE
shopfront-0w1js   1/1       Running   0          2m

Yeah!!!! We’ve just created our first service onto Kubernetes.

As you can see the name of pod is shopfront-0w1js Afther the dash (-) we have a key of pod.

Testing

I will use curl in order to get data from shopfront application’s healthcheck endpoint.

$ curl $(minikube service shopfront --url)/health

And …

{"status":"UP"}

Everything is OK, the application is up and running.

Building the remaining applicactions

We have one container uo and running let’s build the other two supporting microservice applications:

$ cd ..
$ cd productcatalogue/
$ docker run -it --rm -v $PWD:/usr/src/mymaven -w /usr/src/mymaven maven  mvn clean install
…
$ docker build -t tuxisma/djproductcatalogue:1.0 .
...
$ docker push tuxisma/djproductcatalogue:1.0
...
$ cd ..
$ cd stockmanager/
$ docker run -it --rm -v $PWD:/usr/src/mymaven -w /usr/src/mymaven maven  mvn clean install
…
...
$ docker build -t tuxisma/djstockmanager:1.0 .
...
$ docker push tuxisma/djstockmanager:1.0
…

We have built all of our microservices, associated Docker images, pushed the images to Docker Hub. We gonna deploy the “productcatalogue” and “stockmanager” services to Kubernetes.

Deploying the entire Java applications in Kubernetes

$ cd ..
$ cd kubernetes/
$ kubectl apply -f productcatalogue-service.yaml
service "productcatalogue" created
replicationcontroller "productcatalogue" created
$ kubectl apply -f stockmanager-service.yaml
service "stockmanager" created
replicationcontroller "stockmanager" created
$ kubectl get svc
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes         ClusterIP   10.0.0.1       <none>        443/TCP          19h
productcatalogue   NodePort    10.0.0.37      <none>        8020:30160/TCP   42s
shopfront          NodePort    10.0.0.216     <none>        8010:30019/TCP   13m
stockmanager       NodePort    10.0.0.149     <none>        8030:31089/TCP   16s

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
productcatalogue-79qn4   1/1       Running   0          55s
shopfront-0w1js          1/1       Running   0          13m
stockmanager-lmgj9       1/1       Running   0          29s

How looks the complete application

Let’s acces to application via the shopfront servie GUI. Our application will open the service in our default browser on my way is Firefox, use the following command in minikube:

$ minikube service shopfront

See the magic!

shopfront-kubernetes

We’ve deployed our microservices using Kubernetes <3

Source: