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.
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.
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
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.
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.
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 is where we provide details about the resource that is being declared.
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.
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
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