How to Deploy NodeJS Applications in Kubernetes

Deploy NodeJS to Kubernetes

Overview

Kubernetes has caught the attention of nearly every developer and organization. Every major cloud platform provides a hosted solutions, from AWS to GCP. In this tutorial, you will learn how to deploy NodeJS applications in Kubernetes.

You will also learn how to expose your NodeJS application, both internally for other services to subscribe to and externally as a public API. Just as important as deploying your application, scaling services up and down will be covered, as well as how to handle rolling updates.

Getting Started

The run a NodeJS application in Kubernetes, no matter which platform is hosting it, you will need the following installed.

  • Kubernetes Cluster (DigitalOcean, GKE, AKS, EKS)
  • Docker installed locally
  • Kubectl installed locally

Building a Docker Image

In order for your NodeJS application to run in Kubernetes, it will need to be shipped as a container. There are two schools of thought when it comes to deciding how to containerize your applications — use an existing NodeJS image or build your own image.

Using Existing NodeJS Images

Node offers official images for Node.js applications. The simplest, most productive way for getting started in containerizing your application. The following is an example of a Dockerfile for creating a basic container.

FROM node

WORKDIR /usr/src/app

COPY package*.json ./
COPY index.js ./
COPY ./app ./app

RUN npm install

EXPOSE 3000
CMD [ "npm", "start" ]

docker build serverlab:1.0.0 .

Pushing Your Image to a Docker Repository

In order to run your containerized application in Kubernetes it must be available in a Docker repository. The repository must be accessible to the Kubernetes cluster, as it will be pulled down every time a pod container your image is deployed.

Dockerhub is a good start for anyone just getting into Kubernetes. They offer both public and private repositories, and Kubernetes can use both. If you are using Google Kubernetes Engine (GKE), you may use Google repository, for example.

In this tutorial, we will use Dockerhub as the repository for demonstration purposes. We will point to it in our pod and deployment manifests. To deploy our image, we will have to push it up to Dockerhub, which requires us to login first.

docker login

Add a tag to the image you built earlier so that the name includes the repository. When using Dockerhub, it must begin with your DockerID.

docker image tag simple-api:1.0.0 serverlab/simple-api:1.0.0

Now, push your image up to the repository.

docker push serverlab/simple-api:0.0.1

Deploying to Kubernetes

Creating a Pod

A pod is the smallest, atomic part of a Kubernetes cluster. Pods are were your Docker containers run, so let’s start off by creating a pod for the NodeJS application.

Create a new file named simple-api-pod.yml

touch simple-api-pod.yml

Add the following contents to the new file.

apiVersion: v1
kind: Pod
metadata:
  name: simple-api
  labels:
    name: simple-api
spec:
  containers:
  - name: simple-api
    image: serverlab/simple-api:1.0.0
    ports:
    - containerPort: 3000

The example above is a very basic pod declaration. To understand the manifest a little better, the different parts of the file are described below.

apiVersion
The apiVersion is used to let Kubernetes know which schema to use when creating a resource. This value is required to let Kubernetes know which version of the schema should be used when creating the resource.

kind
There are many resources kinds handled by Kubernetes, from pods to ingress controllers. This is a required key that lets Kubernetes know what type of resource is being created.

metadata
Metadata is where we provide details about the resource that is being declared.

spec
The spec is where we declare how our resource must be created. For a Pod, we describe the container image to be used, the name the container will run as, as well as other details, such as ports and environment variables.

Starting and Managing the Pod

The remain operations regarding pods will be done using the kubectl command. There are two ways of creating a resource, such as a pod, in Kubernetes. You can use the kubectl create command or the kubectl apply command. Kubectl apply will be the preferred method in this tutorial, as it allows you to update some of the configurations on the fly.

To create the Pod and start it, run the following command targeting the YAML file created for the NodeJS POD.

kubectl apply -f simple-api-pod.yml

Viewing a list of running pods is done using kubectl get pods command.

kubectl get pods

Without specifying a pod all pods will be listed. We can narrow the results by targeting the name of the pod we are interested in.

kubectl get pods simple-api

Pod Details and Logs

The kubectl get command provides very basic information regarding the health of your pod. When troubleshooting problems with the pod, as in why it isn’t starting successfully, we turn to the kubectl describe command.

kubectl describe pod simple-api

The information provided by the kubectl describe command is helpful. However, there are times that a pod must be debugged via logs. Logs are available using the kubectl log command.

kubectl log simple-api

In order for your application to populate its logs it must print everything to stdout.

Exposing as a Service

Pods are ephemeral, and that means they are not expected to live long. This way of thinking matches the popular cattle, not sheep mantra often heard and repeated.

Service resources provide a static entry way into pods. They are not pods themselves, but resources that direct traffic to any pod attached to it.

Create .new YAML resource file named simple-api-service.yml.

touch simple-api-service.yml

And add the following contents to it.

apiVersion: v1
kind: Service
metadata:
  name: simple-api
spec:
  selector:
    app: simple-api
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000

Create the service resource using the same command used for the pod.

kubectl apply -f simple-api-service.yml

With the service created you can view basic information about it. You can do this by using the kubectl get command, which outputs basic health status.

kubectl get service simple-api-service

When you need more details about the service, the kubectl describe command can be used. In fact, as you’ve seen, it can be used against any resource in Kubernetes.

kubectl describe service simple-api-service

Creating a Deployment for Scaling

Pods are single constructs. They are not very useful for services that need to scale, which is where Deployment resources come in.

Create a new file named simple-api-deployment.yml

touch simple-api-deployment.yml

And then add the following contents to it.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-api-deployment
  labels:
    app: simple-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: simple-api
  template:
    metadata:
      labels:
        app: simple-api
    spec:
      containers:
      - name: simple-api
        image: serverlab/simple-api:1.0.0
        ports:
        - containerPort: 3000

Create the new deployment resource using the kubectl apply command.

kubectl apply -f simple-api-deployment.yml