You are on page 1of 6

Using Containers with Kubernetes

Source: this codelabs.


Original author: Michael Wufka
Updated by: Alessandro Lica’
For any comment or problem, please contact us: tcc@uniupo.it

This exercise is about creating containers on Google cloud platform (GCP) to deploy
applications and using Kubernetes - a container orchestration system - to create and
manage a cluster of containers and setting up a load balancer for failover purposes.
This exercise is divided into three parts:

A. Package a Simple Java Application as a Container


B. Creating a Kubernetes Cluster and Deploying the Application
C. Scaling up the Service and Rolling out and Rolling back an Update

Part A:
For this and the next parts, Google cloud shell was used. First of all, I downloaded a
sample Java application, created with Spring Boot, which is a framework to develop
stand-alone Java applications, with the following command:
git clone https://github.com/spring-guides/gs-spring-boot.git

Then, I moved where code and executables are located, that is in gs-spring-
boot/complete.

To execute the application I ran the following command:


./mvnw -DskipTests spring-boot:run

The application prints on the console a list of beans provided by Spring Boot, and
listens to connections on port 8080.
To test it out, on the console I clicked on the Web Preview Icon, and then on
“Preview on port 8080”:
This action opened a web page whose contents are written in the class
HelloController.java, a class placed in the “~/gs-spring-
boot/complete/src/main/java/com/example/springboot” directory:

Previous operations confirmed that the application worked as intended.


Then, I killed the app from the shell with Ctrl-C, and with the wrapper of the build
tool Maven, mvnw, I packaged the application:
./mvnw -DskipTests package

Subsequently, I enabled Google Container Registry API from the “APIs & Services”
menu, and I pushed there the container image of the sample application with the
following command:
./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \

-Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1

After the completion of the previous command, I see the container image on the
Container Registry tool, with name “hello-java”, “gcr.io” as hostname and private
visibility. $GOOGLE_CLOUD_PROJECT is an environment variable containing the name
of the current GCP project, which in my case was “test-cloud-hpc”:

To run the Docker image just uploaded, I inputted the following command:
docker run -ti --rm -p 8080:8080 \

gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v1
which successfully executed the application.
Following the same steps as earlier, I verified that the web page on port 8080 was
accessible, and then I killed the application.

Part B:
First of all I enabled the Kubernetes Engine API, in the same way as I had enabled
Google Container Registry API in part A.
To create a cluster of containers with Kubernetes, on the console I went to
Kubernetes Engine, and created a new cluster named “cluster-1” specifying
“europe-west2-b” zone as location, and 2 computing nodes in total (leaving the
other settings at their default value).
After a few minutes the cluster became available (it now has a green check mark
next to its name):

After that, I clicked on the Connect button on the right and copied this command to
the shell:
gcloud container clusters get-credentials cluster-1 --zone europe-west2-b
--project test-cloud-hpc
in order to configure kubectl on my current shell session; kubectl is the Kubernetes
command-line tool which I used in part B and C of this exercise.
Now that kubectl was configured, with kubectl version, I got the following
informations, including the major and minor versions for the client and server:

On the shell, I confirmed that the Docker image uploaded earlier was still present in
this way:

And for some reason, the default creation date for docker images is 1 Jan 1970.
Then I finally deployed the docker image with the following command:
kubectl create deployment hello-java --image=gcr.io/test-cloud-hpc/hello-
java:v1
Creating a deployment called “hello-java” using the image uploaded on Container
Registry in Part A. Of course, in the previous command, the actual name of the
project can be replaced by the $GOOGLE_CLOUD_PROJECT environment variable.
In Kubernetes, a pod is a set of containers, in this case only one - the sample
application - and a deployment is a set of pods.
After waiting some time, deployments and pods created with the previous
command became accessible:

By default, if not specified otherwise, deployments start with only one replica per
pod, which is observable in the overlying screenshot.
Since every pod has a locally assigned IP address that can only be reached from
inside the cluster, I needed to expose the deployment to the Internet by creating a
service of type LoadBalancer, which spawns an external IP for the specified group of
pods, that is reachable from the Internet.
I used this exact command:
kubectl expose deployment hello-java --type=LoadBalancer --port 8080
--target-port 8080
This created a service of the specified type and same name of the deployment used
(but this name can be changed with the option --name), using the same port, 8080,
to serve for connections from outside and to connect to the containers.
The result can be viewed in the next screenshot, with the command:
kubectl get services

And as expected, from this moment on, the application hello-java is accessible at the
external-IP and port underlined in the overlying screenshot:
Part C:
Until now, the application only had one running pod; to increase the number of
replicas of the pod, which can be useful to guarantee failover and meet a possible
increasing workload, I ran this command:
kubectl scale deployment hello-java --replicas=3

As we can see in the next screenshot, now the deployment contains three pods: of
this pods, one was created earlier in Part B, while the other two were added with
the overlying instruction.

All of them are in “Running” status, thus can be used anytime by the LoadBalancer
service.

Kubernetes also allows to update deployments without downtime, incrementally


replacing old pods with new pods containing the new Docker image.
To demonstrate this property, I modified the application by changing the greetings
string returned by the HelloController.java class into “Greetings from Kubernetes!”.
In “~/gs-spring-boot/complete” directory I rebuilt the application:
./mvnw -DskipTests package

and uploaded to Container Registry the new version (identified by the TAG v2 at the
end) of the container image with the following command:
./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build \

-Dimage=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2

Next, I changed the image used by the deployment hello-java with this command:
kubectl set image deployment/hello-java \

hello-java=gcr.io/$GOOGLE_CLOUD_PROJECT/hello-java:v2

As we can see in the following screenshot, at the end of this operation, the old pods
got replaced by the new ones containing the new Docker image (in fact they have
different names).
By accessing the web application using the same external IP and port defined earlier,
I got this output, which means that the deployment was updated successfully.

If I want to revert to the previous version, I can input this command:


kubectl rollout undo deployment/hello-java

which will incrementally replace again the pods with new ones containing the old
Docker image:

As we can see in the next screenshot, the rollback was successful and by refreshing
the web page, I obtained again the previous page:

Having finished the exercise, I closed all the used resources to avoid incurring
charges.
Deleting the service: kubectl delete service hello-java
Deleting the Kubernetes cluster:
gcloud container clusters delete cluster-1 --zone europe-west2-b
which did take some minutes:

Lastly, from the console, I deleted the two Docker images of the Java application
from Container Registry.

You might also like