Kubernetes-Minikube: Journey from containerizing webServer to auto-scaling using Kubernetes

Nepal Brothers
6 min readApr 5, 2020

This is a journey of me creating a web-app that runs on the outside of the container to get it running on the Kubernetes, and making it scale as the traffic increases.

the deployment trying to scale to 500 instances
290 out of 500 instances were up. Rest failed, because my CPU can’t handle that many :/

This article is meant to be short, not too descriptive about the concepts that are available in the documentation and over the internet. However, it will help give you clear idea of how a web-app can be deployed in Kubernetes, and how Kubernetes can be leveraged to massively scale.

We will

  1. Run a very simple web-server
  2. Run web-app on Docker
  3. Run web-app on Kubernetes
  4. Exposing the web-app outside the Pod
  5. Scale the instances to 5 instances or any other number
  6. Limiting resource on pods
  7. Horizontal Scaling

We will not

  1. Talk about the security around Kubernetes. That requires a broader discussion and is heavy on concepts.
  2. Talk about adding multiple web-apps in the single Kubernetes cluster

We will now explore the above mentioned steps one by one.

Run a simple web-server

From different programming languages to different frameworks, there are multiple choices for us to be able to use to build the web-server. For this, I have chosen express.js app, simply because it is easier to start, is more familiar to me and is suitable for this illustration.

The web-server returns us the OS and Memory information the JSON, when we hit the endpoint.

Excerpt from https://github.com/rockink/node-sys-info

Steps:

  1. git clone https://github.com/rockink/node-sys-info
    This clones the git repo
  2. cd node-sys-info
  3. npm install
    Install the dependencies
  4. npm start
    Start the server
  5. Test curl http://localhost:3000
    You can also use browser to test

As you see, when we hit the server, we get the JSON output back.

Conclusion: web-app creation

Run the web-app in Docker

Ok great, we have a web-app that just runs! Now, lets make it runnable in the Docker.

Docker understands theDockerfile and uses it to build the image that then can be run in Docker. It also has instruction for Docker that tells on how to start the web-app.

Here is how it looks like in our case:

Example of Dockerfile; see https://github.com/rockink/node-sys-info

Steps:

  1. docker build -t <username>/node-sys-info .
    Notice the username there? It is the username that you have in your image registry. For us, this could just be Docker Registry for us, which holds the images in the docker.
  2. docker push <username>/node-sys-info
    If you would like to upload it in the DockerHub.
  3. docker run -p 8080:3000 -d node-sys-info
    Now, lets run the image. That is it! You are basically running the app in the Docker now. And you are basically porting 3000 from the node to 8080 in your computer.
  4. Test using curl http://localhost:8080 or through the browser.

Conclusion: web-app to docker image

Run the web-app on Kubernetes

Here we know. Kubernetes. So, before running in the Kubernetes, there are few things we would need to know.

Kubernetes has concept of Pods, that is able to run 1 or more containers together. They can communicate with each other via localhost , since port will be different for different container.

Therefore, we will wrap this container in the Pod. The way we do that is:

pod definition

Steps:

  1. Create a Pod description kubernetes-scripts/sys-info-pod.yaml containing the above definition. This basically tells create a Pod with the name sys-info-server containing the image rockink/node-sys-info:v1
  2. Next, run the pod definition using kubectl
    kubectl create -f kubernetes-scripts/sys-info-pod.yaml
  3. Check the status of the pod that you just created. kubectl get pods -label=app-type=web-server
    The STATUS field tells if the pod is running or not.
  4. Incase you don’t see that status, you can check the logs via kubectl logs -f sys-info-server
  5. We cannot directly connect to the Pod. Therefore, we will need to query it inside the pod directly.
    kubectl exec -it sys-info-server /bin/bash
    curl http://localhost:8080
kubectl get pods -label=app-type=web-server
kubectl exec -it sys-info-server /bin/bash

Exposing the website outside the Pod

Great. Now is the time to get familiar with another new concept: Service

Kubernetes has something called Service that basically acts as a load-balancer and redirects the traffic that it receives and sends it to these pods. Service with the type: NodePort that basically exposes the service outside of its node.

Steps:

  1. Create the above Service definition inkubernetes-scripts/sys-info-service.yaml
  2. Send it to the Kubernetes kubectl apply -f kubernetes-scripts/sys-info-service.yaml
  3. Check if the service is there kubectl get services
  4. Test: Lets now hit our web-app
    curl http://$(minikube ip):30100

You just basically made your service run in the kubernetes! Congrats!

Scale the instances

Okay, we got a lot done. We started from the web-app to actually starting the app in the Kubernetes. Here is what is really amazing about Kubernetes. It is how we can scale the instances of the Pods.

The way we do so is through Deployment, that controls the Pods (if you get deeper, you would know about replication controller, but it is okay to ignore it for this). Deployment identifies the pods through labels and that is how it scales the pod with the matching labels.

Here is the definition of Deployment:

deployment to create 5 replicas of the web-server we created

Steps:

  1. Lets start by deleting the pod that we created manually.
    kubectl delete pods sys-info-server
  2. Create a Deployment definition kubernetes-scripts/sys-info-deployment.yaml. You can also remove the pod definition, as this substitutes pod definition.
  3. Next, send it to the kubernetes.
    kubectl apply -f kubernetes-scripts/sys-info-deployment.yaml
  4. Watchout the pods being generated. We basically are quering using the label that we assigned to the pods.
    kubectl get pods --selector=app-type=web-server
  5. Test: Lets hit the service with the curl command: while true; do curl -s http://$(minikube ip):30100; done
    You will see the different hostnames, as they represent different instance of the container, but for the same web-app.

Lets run this and verify that there are 5 instances of the pods

kubectl get pods --selector=app-type=web-server

shows 5 pods that Deployment just created
while true; do curl -s http://$(minikube ip):30100; done

Limiting resource on pods

We can limit mainly 3 kinds of resources on containers present in the pod, but we will be using here 2 kinds of resources, cpu and memory. They will be defined in the Pod’s container’s spec.

Steps:

  1. Send it to the Kubernetes.
    kubectl apply -f kubernetes-scripts/sys-info-deployment.yaml
  2. See the result: kubectl describe pods

Horizontal Scaling

What if instead of us auto-scaling, we can have let Kubernetes scale the app itself! Lets do that.

Steps:

  1. Enable the metrics-server minikube addons enable metrics-server
  2. Verify it is enabled. minikube addons list | grep metrics
  3. Run the above definition kubectl apply -f kubernetes-scripts/deployment.yaml (see how we can use multiple yamls in the same place)
  4. Now, to see it in action, run multiple curl clients and hit the server. Watch the Kubernetes pods being deployed as necessary through command line
  5. kubectl get hpa provides the current status of scaling. Check out Target field <currentValue>/<expectedValue>
  6. kubectl get deployments sys-info-deployment and check out the number of pods being created.

With this, you literally have a auto-scaling web-server in Kubernetes that you can use.

Congrats! You have completed this whole thing! And thank you for reading!

--

--