Kubernetes with NodeJS

Mohammad Faisal - Jun 21 '23 - - Dev Community

To read more articles like this, visit my blog

Let's deploy a NodeJS application on Kubernetes Cluster

In a previous article we learned the basics of Kubernetes concepts.

Today we will learn how we can deploy a NodeJS application on a Kubernetes cluster. The steps are as follows

  • Create a Docker Image for a NodeJS application
  • Publish that Image to DockerHub
  • Create a Linode Kubernetes Cluster
  • Install Kubectl on our local machine
  • Deploy our application into the Kubernetes cluster

Let's begin!

Create a Docker Image

In a previous article, we learned how we could dockerize a basic NodeJS application.
You can find that article here:

The repository for that article can be found here

So let's clone it first!

git clone https://github.com/Mohammad-Faisal/express-typescript-docker.git

cd express-typescript-docker
Enter fullscreen mode Exit fullscreen mode

So we now have a NodeJS application that is already Dockerized!

Publish an image on Dockerhub

Dockerhub is a place where you can publish your repositories. It's a kind of Github for Docker images, and it's free to use! So feel free to open an account here

Then before we can publish the image, we have to build it.

docker image build -t 56faisal/learn-kubernetes:1.0 .
Enter fullscreen mode Exit fullscreen mode

Notice here,

56faisal -> is the Dockerhub Username
learn-kubernets -> is the image name and
1.0 -> is the tag name
Enter fullscreen mode Exit fullscreen mode

If you are running a Mac, then your default Docker system will use arm64 architecture. But on Linode, your VMs are most likely built using amd64 architecture. This version mismatch will cause a problem when you deploy the image. So if you are on Mac, build your image using the following command.

docker image build  --platform=linux/amd64 -t 56faisal/learn-kubernetes:1.0 .
Enter fullscreen mode Exit fullscreen mode

Then see the image on the list locally.

docker image ls


REPOSITORY                                TAG                   IMAGE ID       CREATED        SIZE
56faisal/learn-kubernetes                 1.0                   13a974972901   2 hours ago    263MB
Enter fullscreen mode Exit fullscreen mode

Then log in to Dockerhub

docker login --username docker_hub_id # for me it's 56faisal
Enter fullscreen mode Exit fullscreen mode

It will ask for your password. Give that, and you should be good to go.

Then push the image to Dockerhub.

docker image push 56faisal/learn-kubernetes:1.0
Enter fullscreen mode Exit fullscreen mode

You can go to Dockerhub and verify that your image is there. For me, the URL looks something like this:

https://hub.docker.com/repository/docker/56faisal/learn-kubernetes
Enter fullscreen mode Exit fullscreen mode

Let's Deploy!

But before we do that, we need to install kubernetes-cli

brew install kubernetes-cli
Enter fullscreen mode Exit fullscreen mode

You can get installation instructions for other OS here

Create Kubernetes Cluster on Linode

There are many Kubernetes services, but Linode offers the easiest way to manage them. So we will create a kubernetes cluster with two worker nodes on Linode.

I will not go into the details of that. You can follow this link to do that.

Get the Kubernetes cluster configuration

On your Linode Kubernetes cluster page, you will notice that there is a download button for your Kubernetes config file.

Download that and put that into the root of the project. Or anywhere, for that matter. This will allow us to interact with the Kubernetes cluster later on.

Open a terminal and save the kubeconfig's path to the $KUBECONFIG environment variable.

You can get the current directory path by running pwd and use that to get the path to your config file.

Let's set the context for us now!

export KUBECONFIG=/Users/mohammadfaisal/Documents/learning/express-typescript-docker/learn-kubernetes-kubeconfig.yml
Enter fullscreen mode Exit fullscreen mode

Then run the following command to see the nodes! Nodes are physical machines or VMs that run on the cloud.

kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

We created two servers on our Linode cluster. So we will see two nodes.

NAME                          STATUS   ROLES    AGE   VERSION
lke55618-87276-6237a2503845   Ready    <none>   33m   v1.22.6
lke55618-87276-6237a2510769   Ready    <none>   33m   v1.22.6
Enter fullscreen mode Exit fullscreen mode

The nodes are ready to run our applications.

Create a deployment

So now we can interact with our Kubernetes cluster.
But now we need actually to deploy something to understand it's power. Kubernetes has a concept of pods. Pods are independent containers that run on your infrastructure.

You can create as many pods as you want, and you can do that by configuring the deployment. What it means is you can have 20 pods on your two machines. And generally, we have one container inside one pod.

Let's create a deployment configuration named deployment.yml and paste the following configuration there.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: learn-kubernetes-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: express-docker-kubernetes
  template:
    metadata:
      labels:
        app: express-docker-kubernetes
    spec:
      containers:
      - name: express-docker-kubernetes
        image: 56faisal/learn-kubernetes:1.0
        ports:
        - containerPort: 3000
Enter fullscreen mode Exit fullscreen mode

Here some of the important things to note are the following:

selector -> matchLabels -> app -> express-docker-kubernetes

This app helps us to name our pods. Later, it will help us modify our deployments and relate them to services.

Deploy your application

Then deploy this using the following command.

kubectl create -f deployment.yml
Enter fullscreen mode Exit fullscreen mode

We pass the deployment.yml file using the -f configuration. This allows us to create multiple deployment files for different folders.

You can see the deployments by running the following command:

kubectl get deployments
Enter fullscreen mode Exit fullscreen mode

If you want details of the deployment:

kubectl explain deployment
Enter fullscreen mode Exit fullscreen mode

and this will give an output like this

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
learn-kubernetes-deployment   0/2     2            0           7s
Enter fullscreen mode Exit fullscreen mode

If you want to delete the deployment, you can run the following command:

kubectl delete deploy learn-kubernetes-deployment
Enter fullscreen mode Exit fullscreen mode

Here the last part is the name of the deployment.

See the pods

Your deployment has created two pods because we gave our deployment configuration the option replicas:2.

Let's see those pods!

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

It will give you an output like this.

NAME                                          READY   STATUS    RESTARTS   AGE
learn-kubernetes-deployment-6fdf4bf45-pglg8   1/1     Running   0          49m
learn-kubernetes-deployment-6fdf4bf45-s9dsd   1/1     Running   0          49m
Enter fullscreen mode Exit fullscreen mode

So both of our pods are running! If you need to scale up, you need to increase the number from 2 to whatever you want and re-deploy it.
It's that easy!

Sometimes you will need to see what's going on inside your pods. You can get more details from the pods using the following commands.

kubectl describe pods
Enter fullscreen mode Exit fullscreen mode

The output will have all the information you will need, including the IP addresses of the pods. But unfortunately, you will not be able to access your application yet because your application is not exposed to the world yet!

Let's do that now!

Show it to public

Let's expose the deployment to the world using the following command.

kubectl expose deployment learn-kubernetes-deployment --type="LoadBalancer"
Enter fullscreen mode Exit fullscreen mode

or else we can create a service for the deployment as well

apiVersion: v1
kind: Service
metadata:
  name: learn-kubernetes-service
spec:
  selector:
    app: learn-kubernetes
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000
Enter fullscreen mode Exit fullscreen mode

Then run

kubectl apply -f service.yml
Enter fullscreen mode Exit fullscreen mode

And that will create a load balancer for our application on the Linode server, and we will get a public endpoint to call our service.

Once you successfully deploy the service, get the details of the load balancer by running the following command:

kubectl get services
Enter fullscreen mode Exit fullscreen mode

And you will see the following output:

NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
kubernetes                 ClusterIP      10.128.0.1       <none>           443/TCP          4h58m
learn-kubernetes-service   LoadBalancer   10.128.247.181   172.105.44.102   3000:31752/TCP   74s
Enter fullscreen mode Exit fullscreen mode

Notice the EXTERNAL-IP column that gives you your application's public IP address.

Let's head over to your browser and hit the following URL

http://172.105.44.102:3000/
Enter fullscreen mode Exit fullscreen mode

And you will be greeted with the following output.

{ "message": "Hello World!" }
Enter fullscreen mode Exit fullscreen mode

Our application is live now! And we can do whatever we want with it!

Congratulations on deploying your first NodeJS application using Kubernetes.

Github Repo:

https://github.com/Mohammad-Faisal/nodejs-docker-kubernetes

Have a great day! :D

Get in touch with me via LinkedIn or my Personal Website.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .