Kubernetes with NodeJS
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
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 .
Notice here,
56faisal -> is the Dockerhub Username
learn-kubernets -> is the image name and
1.0 -> is the tag name
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 .
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
Then log in to Dockerhub
docker login --username docker_hub_id # for me it's 56faisal
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
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
Let's Deploy!
But before we do that, we need to install kubernetes-cli
brew install kubernetes-cli
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
Then run the following command to see the nodes! Nodes are physical machines or VMs that run on the cloud.
kubectl get nodes
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
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
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
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
If you want details of the deployment:
kubectl explain deployment
and this will give an output like this
NAME READY UP-TO-DATE AVAILABLE AGE
learn-kubernetes-deployment 0/2 2 0 7s
If you want to delete the deployment, you can run the following command:
kubectl delete deploy learn-kubernetes-deployment
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
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
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
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"
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
Then run
kubectl apply -f service.yml
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
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
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/
And you will be greeted with the following output.
{ "message": "Hello World!" }
Our application is live now! And we can do whatever we want with it!
Congratulations on deploying your first NodeJS application using Kubernetes.