A two containers application from Docker to Kubernetes

Vicente Coopman
6 min readMay 11, 2021

Context

As a Computer Science student, I’m taking a introductory course on Microservices Architecture. Last week lecture was about Scaling and the different ways to do so. The teacher gave us an assigment, to migrate our two container application from Docker (using docker-compose) to Kubertenes.

I looked up for references or simple examples on how to do this, but I didn’t really find anything straight to the point or something I could easily understand. That’s why I decide to share this assignment. I hope it helps :)

To help me I used some examples from the Kubernetes website, like this one.

There is a really cool introductory tutorial on the Kubernetes website. Link here

Introduction

I will assume that if your are looking to migrate from Docker to Kubernetes you already know about Docker. If not, you can check this introductory guide wrote by Prakhar Srivastav.

So, what is Kubernetes? It is a container-orchestration system for automating application deployment, scaling and managment. It is another layer of abstraction above containers. That allow us to manage those containers at a large scale. (Link to documentation)

What are we gonna do? From a two container application, deployed using docker-compose, we will deploy it in a local Kubernetes cluster.

The application that we will use can be found here, under “docker/dockerfiles/books”. You will need to clone the repository if you want to follow along.

This example application uses the python Hug framework and mysql database. The application is meant to be an API for a book managment system.

Disclaimer 1: This is a Stateless Application, we won’t worry about the data stored in our app.

Disclaimer 2: I’m far far away from being an expert in Docker or Kubernetes.

Let’s begin!!

Step 1: Install kubectl

kubectl is the tool that allow us to interact with our Kubernetes cluster (We don’t have a cluster yet, but we will 😉)

This are the steps for Linux, if you have another OS or a problem with the installation, you can see the official page.

1.1 Update the apt package index and install packages needed to use the Kubernetes apt repository:

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

1.2 Download the Google Cloud public signing key:

sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

1.3 Add the Kubernetes apt repository:

echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

1.4 Update apt package index with the new repository and install kubectl:

sudo apt-get update
sudo apt-get install -y kubectl

1.5 Check if it is installed correctly:

kubectl version

If everything is OK, you should get something like:

Client Version: version.Info{Major:"1", Minor:"21", ...

Don’t worry if you get some warnings about “connection to the server refused”, we will cover that in the next step.

Step 2: Create a Kubernetes cluster

For learning purposes, the Kubernetes website recommend 3 tools to create a cluster. In this case we will go with the tool Kind.

2.1 Install kind:

curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.10.0/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

2.2 Create a Kubernetes cluster using kind:

kind create cluster --name kind-1 # default name is 'kind'

This will automatically create a cluster named “ kind-1 “ and set everything up. If you are not sure about Kubernetes cluster architecture, you can read here.

2.3 Check versions again:

kubectl version

The output should now look like:

Client Version: version.Info{Major:"1", Minor:"21", ...
Server Version: version.Info{Major:"1", Minor:"20", ...

You must use a kubectl version that is within one minor version difference of your server!

Step 3: Load your Docker images to the cluster

This is because Kubernetes relies on the fact that images described in a Pod manifest are available across every machine in the cluster. For more info about Pods read here.

3.1 Build the Docker images:

# From the project directorydocker build -t books:latest docker/dockerfiles/books/# Pull the database imagedocker pull mysql:8

This will create our books:latest image and pull the image for our database.

3.2 Load the images into our Kubernetes cluster:

kind load docker-image books:latest --name kind-1kind load docker-image mysql:8 --name kind-1

Step 4: Define the Deployment and Service for the MySql Database

Now you will ask, what is a deployment? what is a service?

Quick answer:

A deployment is a resource object that describes the desired state of the applications. A deployment allow you to describe an application’s life-cycle, for example wich image to use for the application, the number of replicas of the pod and the way in which they should be updated. Read more

A service is an abstract way to expose an application running on a set of Pods as a network service. Read more

Now we can continue, 😛

4.1 Define the deployment for the database:

We set replicas to 1, so all the instances of the books app will talk to the same database. We also define a container that will use the mysql:8 image that we load into our cluster.

If you want a deeper explanation, in the link above about deployments, you can read more about how to write them.

4.2 Define a service for our database:

This will allow us to communicate from the books app to the MySql database.

4.3 Apply the deployment and the service:

# from the project_dir/kuberneteskubectl apply -f deployments/mysql-deployment.ymlkubectl apply -f services/mysql-service.yml

4.4 Verify resources were created:

kubectl get pods

The output should look like,

NAME                            READY     STATUS    RESTARTS   AGE
mysql-5cfd459dd4-ad5d4 1/1 Running 0 28s

And for the service,

kubectl get services

The response should be similar to:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
mysql ClusterIP 10.0.0.159 <none> 27017/TCP 30s

Step 5: Define the Deployment and Service for the books app

Now we will do the same for the app.

5.1 Define the deployment for the app:

Notice that we set replicas to 4, this will create and maintain 4 instances of our app.

Check the list of pods:

kubectl get pods -l app=books

Should ouput something like,

NAME                            READY     STATUS    RESTARTS   AGE
books-6c757d898-ad5d4 1/1 Running 0 4s
books-6c757d898-3v5ds 1/1 Running 0 4s
books-6c757d898-xc5d1 1/1 Running 0 4s
books-6c757d898-adedc 1/1 Running 0 4s

5.2 Define the app service:

Note that we set the type to “ LoadBalancer “, this should normally give us an external-ip, but due that we are using a custom Kubernete cluster, there is no LoadBalancer integrated. So we get an external-ip <pending>.

We can see the service using:

kubectl get service -l app=books

and the service and the issue:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP  PORT(S)
books-service LoadBalancer 10.0.0.112 <pending> 8000:32564/TCP

We will bypass this and test our app in the next and final step.

Step 6: View the books app service via “kubectl port-forward”

kubectl port-foward allows us to interact with a internal Kubernetes cluster processes from your localhost. We will forward the port of our books service so we can test it.

# in a new terminalkubectl port-forward svc/books-service 8000:8000

This process will not return. Use another terminal for this. Response should look like:

Forwarding from 127.0.0.1:8080 -> 8000
Forwarding from [::1]:8080 -> 8000

NOW FINALLY, test the deployment.

curl localhost:8000/books/1

And the response should be:

That was a lot of work 😰, but we finally made it! 😄

Conclusion

We saw from installing kubectl to deploying a two container application into a Kubernetes cluster. Sure there are a many things that I didn’t explain, but as I said, I wanted this to be “ straight to the point”. I hope this helps you. Remember that the source code is on github.

--

--

Vicente Coopman
0 Followers

Computer Science Student — Universidad de Concepción, Chile