Deploying a Node.js Application to Kubernetes using Helm and Helm Charts

487 VIEWS

·

This article will teach you how to deploy a Node.js application to Kubernetes using Helm and Helm charts. Node.js is an open-source Javascript runtime for building server-side applications. 

Kubernetes is an open-source platform that automates the deployment and management of containerized applications. Kubernetes orchestrates containerized applications and deploys them into a Kubernetes cluster. 

A Kubernetes cluster contains a set of worker and master nodes. The nodes have resources for running the deployed containerized applications.

In this article, we will create a Node.js application and run it locally. We will then containerize the application using Docker. Finally, we will deploy the Dockerized Node.js application to Kubernetes using Helm and Helm charts.

Prerequisites

For you to implement the concepts in this Helm article in the easiest way: 

  • You must have some experience with Docker 
  • Understand the working of Kubernetes and creating Kubernetes YAML files.
  • Know how to run kubectl commands on a Kuberenetes cluster. Kubectl helps in the deployment and management of applications. It also allows developers to communicate and interact with the Kubernetes cluster.

You also need to set up the following tools:

  • Node.js: Javascript runtime: For building the Express Server.
  • Docker: For containerizing the Node.js application. You must know how to create and work with Docker containers. If you are new to Docker, you can read this article.
  • Vs Code: For code editing.

Note: I will show you how to install the other necessary tools. These three are the most important for you to have to get started faster.

What is Helm?

Helm is a package manager for Kubernetes applications. It packages a collection of Kubernetes YAML files and distributes them in a public and private registry. Helm bundles Kubernetes YAML files into a package known as a Helm Chart. Kubernetes YAML files are also known as Kubernetes manifest files for creating Kubernetes objects such as Kubernetes Deployment, Kubernetes Service, Configmaps, and Secrets.

These files are for deploying any containerized application to Kubernetes. We use Helm Charts as a blueprint for deploying any Kubernetes application. 

You will modify some of the configurations in the YAML files in the Helm Chart. You can also create your custom Helm Chart. 

We will install Helm and generate a custom Helm Chart for our Node.js application. We will then modify the YAML files in the Helm before deploying the Node.js application to Kubernetes. To understand more about Helm, read this article on Sweetcode.

I will show you how to install Helm later. Let’s first create and containerize a basic Node.js application with an Express get route.

Creating a Basic Node.js Application

We will create an Express server with a get route using Node.js. If you are new to Node.js, you can read this article to gain a better understanding. Let’s now create a basic Node.js application.

To start, create a new folder named `node-js-app`, and open it with VS Code. Next, initialize the Node.js application using the following command:

npm init-y

The working environment for our application is ready. Let’s install the dependencies for this application:

npm install express

We will use `express` to create an Express server route. In the `node-js-app` folder, create an `index.js` file. Open the file and add the following code:

const express = require('express')
const cors = require('cors')

const app = express()

app.use(cors())

app.get('/', (req, res) => {
  res.json([
    {
      "id": "1",
      "title": "This is my First Blog Title"
    },
    {
      "id": "2",
      "title": "This is my Second Blog Title"
    },
    {
      "id": "3",
      "title": "This is my Third Blog Title"
    },
    {
      "id": "4",
      "title": "This is my Fourth Blog Title"
    },
    {
      "id": "5",
      "title": "This is my Fifth Blog Title"
    }
  ])
})

app.listen(4000, () => {
  console.log('Server running on port 4000')
})

The code will create a get route that displays the five blog titles. To run the Express server, use this command:

node index.js

The command will start the Express server on port `4000` as shown below:

You can then type http://localhost:4000 on your browser to view the running Express server:

Our Node.js application is running locally, let’s now containerize the application using Docker.

Containerizing the Application using Docker

We will start by building a Docker image for the Node.js application. To build a Docker image, we will need a `Dockerfile`. A `Dockerfile` contains commands (list of instructions) for building the Docker image. Let’s create our `Dockerfile` that the Docker Daemon will use:

Creating the Dockerfile

In the `node-js-app` folder, create a `Dockerfile` and add the following commands:

# It will pull node:18-alpine as the base image from Docker Hub
FROM node:18-alpine

# It creates the container working directory named `node`
WORKDIR /node

# It copies all the dependencies and libraries to the working directory
COPY package.json .

#It installs all the dependencies and libraries to the container
RUN npm install

#It copies all the source code and configuration files to the container working directory
COPY . .

#it exposes and runs the container to port 4000
EXPOSE 4000

#It is the command to start and run the container for the Node.js application
CMD ["node", "index.js"]
Building the Docker Image

To build the Docker image using the Dockerfile above, run this Docker command in your terminal:

docker build -t <Docker Hub username>/node-app .

Remember to use your Docker Hub username when naming the Docker Image. The command will build a Docker image as shown below:

Pushing the Image to Docker Hub

To push the Docker image to Docker Hub, apply the following Docker commands sequentially:

docker login
docker push <Docker Hub username>/node-app

After successfully pushing the Docker image to Docker Hub, let’s run the Docker image.

Running the Docker Image

When you run a Docker image, it automatically starts and runs a Docker container. To run this image, apply the following Docker command:

docker run -p 4000:4000 <Docker Hub username>/node-app

The command will start and run the Docker container on port 4000. You can type http://localhost:4000 on your browser to view the application running a Docker container:

We have containerized the Node.js application. Let’s now install Helm.

Installing Helm

We will install Helm on a Kubernetes cluster. In this guide, we will install Helm on a local Kubernetes cluster engine known as Minikube. Minikube allows developers to create and run the Kubernetes cluster on their local computer/machine. You can read this article on Sweetcode to gain a better understanding of Minikube.

 

Minikube does not require any installation since it comes with Docker Desktop. Before we install Helm, let’s start Minikube. You will apply the following `minikube` command in your terminal:

minikube start --driver=docker

The output below shows Minikube is running and using Kubectl:

Now that Minikube is running, let’s install Helm:

1. Install Helm on macOS

To install Helm on macOS, use this `brew` command from the Homebrew package manager:

brew install helm

2. Install Helm on Linux

To install Helm on Linux, run this `apt` command to :

sudo apt-get install helm

3. Install Helm on Windows

To install Helm on Windows, use this `choco` command from the Chocolatey package manager:

choco install kubernetes-helm

In this guide, I have installed Helm using `choco` as shown below:

To see some of the Helm commands, run this command in your terminal:

helm

It outputs the following Helm commands:

To check the Helm version, run this Helm command:

helm --version

The version output:

Creating a Helm a Chart

We will create a Helm chart `node-app-chart` for the Node.js application. The Helm chart will contain the default YAML files. We will modify the files before deploying our application. To create the Helm chart, run this Helm command:

helm create node-app-chart
Helm Chart Structure

To get the structure of the created Helm chart, run this command:

ls node-app-chart

The structure for the `node-app-chart` is shown below:

You can also open the `node-app-chart` folder in VS Code as shown below:

From the image above, the `node-app-chart` contains the Charts folder, Template folder, Chart.yaml file, and the Values.yaml file. 

1. Charts folder

This folder contains any other dependencies for the `node-app-chart`.

2. Template folder

This folder contains all Kubernetes YAML or manifest files for creating Kubernetes objects such as Kubernetes Deployment, Kubernetes Service, Configmaps, and Secrets. In this guide, we will only require the `deployment.yaml` and `service.yaml`. We will modify these two files and add our configurations for deploying the Node.js application.

3. Chart.yaml

This YAML file contains descriptive information about the Helm chart such as the chart name and version.

4. Values.yaml

This YAML file contains the application configuration values that the other YAML files in the template folder will use. These values include the image name, container name, port mapping, number of pods, and the type of Kubernetes service. 

In this guide, the `deployment.yaml` and `service.yaml` files will read and use the values in this file during the deployment. 

Let’s start by modifying the Values.yaml file.

Modifying the Values.yaml File

Open the Values.yaml file and modify it using the following YAML code:

replicaCount: 2

image:
  repository: <Docker Hub username>/node-app
  pullPolicy: IfNotPresent
  tag: "latest"

service:
  type: LoadBalancer
  port: 4000
  targetPort: 4000
  protocol: TCP
  name: node-app-service

resources: {}
limits:
    cpu: 100m
    memory: 256Mi
requests:
    cpu: 100m
    memory: 256Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80

Let’s modify the `deployment.yaml` and `service.yaml` files.

Modifying the deployment.yaml File

Open the deployment.yaml file and modify it using the following YAML code:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "node-app-chart.fullname" . }}
  labels:
    {{- include "node-app-chart.labels" . | nindent 4 }}
spec:
  {{- if not.Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "node-app-chart.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      labels:
        {{- include "node-app-chart.selectorLabels" . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default.Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: 4000
              protocol: TCP
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

Modifying the service.yaml File

Open the service.yaml file and modify it using the following YAML code:

apiVersion: v1
kind: Service
metadata:
  name: {{ include "node-app-chart.fullname" . }}
  labels:
    {{- include "node-app-chart.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetPort }}
      protocol: {{ .Values.service.protocol }}
      name: {{ .Values.service.name }}
  selector:
    {{- include "node-app-chart.selectorLabels" . | nindent 4 }}

All the files we need for this guide are ready. Let’s now deploy the Node.js application to Kubernetes this Helm Chart.

Deploying the Node.js Application

To deploy the Node.js application to Kubernetes this Helm Chart, run this `Helm` command:

helm install node-app-chart

When you run the Helm command above, the following happens:

  • Helm will automatically go through all of the files. 
  • It will then read the application configuration values and pass them to the two files: `deployment.yaml` and `service.yaml`. 
  • The final `deployment.yaml` and `service.yaml` files will have the correct configuration value for the Node.js application. 
  • Helm will use these files to create the Kubernetes objects and deploy the Node.js application to the Kubernetes cluster.

After a while, the `node-app-chart` will be deployed as shown below:

Let’s use Kubectl to get the created pods, Kubernetes Deployment, and Service:

Pods

To get all the created pods, use this command:

kubectl get pods

Kubernetes Deployment

To get the Kubernetes Deployment, use this command:

kubectl get deployment

Kubernetes Service

To get the Kubernetes Service, use this command:

kubectl get service

We will use the created Kubernetes service to access the application.

Accessing the Node.js Application using Kubernetes Service

To access the application, run this Minikube command:

minikube service node-app-chart

Minikube will start a tunnel for `node-app-chart` and assign a unique URL to the application as shown below:

You can input the URL in your web browser to access the application:

From the image above, you can see that our Node.js application runs inside the Kubernetes Cluster. We have successfully deployed this application using Helm and Helm Chart.

Conclusion

In this guide, we have learned how to deploy a Node.js application to Kubernetes using Helm and Helm Charts. Helm is a package manager for Kubernetes applications. 

It helps developers get started with Kubernetes. It simplifies the process of deploying the Kubernetes application. You only need to modify the YAML files once you have created a Helm Chart. Charts. Thank you all for reading, and Happy Helming!


Mehmet is an experienced DevOps engineer and data science enthusiast. He has a Bachelor's Degree in Computer Science and has an AWS certification. He has experience working with Kubernetes Cloud Providers such as Amazon EKS, Azure AKS, DigitalOcean Kubernetes and Google Cloud Engine. He also has experience working with other DevOps tools such as Jenkins CI/CD Pipeline as Code and Terraform Infrastructure as Code.


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar