Kubernetes-Minikube: Journey from containerizing webServer to auto-scaling using Kubernetes
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.
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
- Run a very simple web-server
- Run web-app on Docker
- Run web-app on Kubernetes
- Exposing the web-app outside the Pod
- Scale the instances to 5 instances or any other number
- Limiting resource on pods
- Horizontal Scaling
We will not
- Talk about the security around Kubernetes. That requires a broader discussion and is heavy on concepts.
- Talk about adding multiple web-apps in the single Kubernetes cluster
We want the code right way!
You asked, and here it is!
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.
Steps:
git clone https://github.com/rockink/node-sys-info
This clones the git repocd node-sys-info
npm install
Install the dependenciesnpm start
Start the server- 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:
Steps:
docker build -t <username>/node-sys-info .
Notice theusername
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.docker push <username>/node-sys-info
If you would like to upload it in the DockerHub.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.- 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:
Steps:
- 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 - Next, run the pod definition using
kubectl
kubectl create -f kubernetes-scripts/sys-info-pod.yaml
- 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. - Incase you don’t see that status, you can check the logs via
kubectl logs -f sys-info-server
- 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
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:
- Create the above Service definition in
kubernetes-scripts/sys-info-service.yaml
- Send it to the Kubernetes
kubectl apply -f kubernetes-scripts/sys-info-service.yaml
- Check if the service is there
kubectl get services
- 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:
Steps:
- Lets start by deleting the pod that we created manually.
kubectl delete pods sys-info-server
- Create a Deployment definition
kubernetes-scripts/sys-info-deployment.yaml
. You can also remove the pod definition, as this substitutes pod definition. - Next, send it to the kubernetes.
kubectl apply -f kubernetes-scripts/sys-info-deployment.yaml
- 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
- 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
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:
- Send it to the Kubernetes.
kubectl apply -f kubernetes-scripts/sys-info-deployment.yaml
- 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:
- Enable the metrics-server
minikube addons enable metrics-server
- Verify it is enabled.
minikube addons list | grep metrics
- Run the above definition
kubectl apply -f kubernetes-scripts/deployment.yaml
(see how we can use multiple yamls in the same place) - 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
kubectl get hpa
provides the current status of scaling. Check out Target field <currentValue>/<expectedValue>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!