Deploy Auto-Scalable Node.js Application on Kubernetes Cluster — Part 1


We are facing crazy technologies everyday, and we — as developers — need to decide on ones that are more production ready. During this decision period, there are several parameters we use to convince our selves. Being able to simulate some production environment behaviours on developer machine is a must if I will say it is crazy. In this tutorial, we will create a Kubernetes cluster with Minikube on our local computer and then deploy a sample Node.js application to this cluster in a way that scales according to load from out side.

Kubectl

Kubectl is a command line tool for running commands on Kubernetes cluster. You can install it via;

curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/darwin/amd64/kubectl

It will be enabled after granting execution permission and moving to user local folder.

chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl

You can verify it with kubectl version

Kubectl Version

From now on, we will be able to access Kubernetes cluster with kubectl. If you are using different operating system, you can refer installation instructions here

Minikube

Minikube is a tool let us create Kubernete cluster on our local computer. You can install minikube with following command,

brew cask install minikube

If you are using different operating system, you can refer installation instructions here

We can start a Kubernetes cluster locally by executing minikube start

Minikube start

As you can see on the output, our kubectl client is autoconfigured automatically to connect local kubernetes cluster. To test this, you can list services with;

kubectl get services

Kubectl services

Sample Node.js Application

Here is a sample yet another Hello World Node.js application.


const http = require(‘http’);
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader(‘Content-Type’, ‘text/plain’);
res.end(‘Hello Worldn’);
});
server.listen(port, () => {
console.log(`Server running on port: ${port}`);
});

This application runs on port 3000 if you have no environment variable with key PORT .

Docker Image Preparation

In order to deploy this app on Kubernetes, we can prepare a Dockerfile to build a docker image for future use. Dockerfile comes as following;

FROM node:alpine

RUN mkdir -p /usr/src/app

WORKDIR /usr/src/app

ADD index.js ./

ADD package.json ./

RUN npm install

CMD ["npm", "start"]

I assume you have already a Docker Hub account, and when you execute followings, you will be able to push your image to Docker Hub. Do not forget to replace <username> section below.

docker login
docker build -t <username>/node-example .
docker push <username>/node-example

Now we are ready to use this docker image on our Kubernetes deployments.

Kubernetes Deployments & Services

The project conventions for my Kubernetes projects on my daily basis as follows;

  • Create a folder k8s inside your project
  • Create deployment.yml inside k8s
  • Create service.yml inside k8s

In deployment file, we simply define our project metadata and container definitions to manage pods. Here is our deployment.yml file;

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: node-example-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: node-example
spec:
containers:
- name: node-example
image: huseyinbabal/node-example
imagePullPolicy: Always
ports:
- containerPort: 3000

You can see this is a deployment object by looking at kind keyword. With replicas keyword, I am saying that this will have only one instance beyond the service. In containers section, we provided our docker image, and port number for container internals.

We are ok with the deployment, and let’s expose our app to real world. This time we will have a service file like below;

apiVersion: v1
kind: Service
metadata:
name: node-example
labels:
app: node-example
spec:
selector:
app: node-example
ports:
- port: 3000
protocol: TCP
nodePort: 30001
type: LoadBalancer

We are simply exposing our port 3000 as 30001 to outside and this is a service with LoadBalancer type. Now go to your project folder and execute following;

kubectl apply -f k8s

This command will create/update service and deployment on Kubernetes cluster by using service and deployment definitions inside necessary files in project.

Kubectl apply

In order to check your deployment and services, you can use commandline;

Kubectl service

Kubectl deployments

Kubectl pods

As you can see, we have 1 running pod beyond our service. You can see above status by using minikube also;

minikube dashboard

Minikube dashboard

Now we are ready to access our service by using;

minikube service node-example

This will open our service inside a browser by using kubernetes internals.


You can access Github project here

Conclusion

To sum up; we simply created a Kubernetes cluster by using minikube, and this enabled us using our kubectl to connect Kubernetes cluster. Node.js application helped us to test our deployments. In this tutorial, I mainly focused on Kubernetes preparation and application deployment. In next tutorial, I will show you how to scale your application manually/automatically with supporting benchmark operations.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s