Deploy a Node.js app in Red Hat Openshift using source-to-image (S2I)

Deploy a Node.js app in Red Hat Openshift using source-to-image (S2I)

In my previous blog, I wrote how to install Red Hat Openshift local on a personal laptop. Now, it’s time to step ahead and explore the local Openshift cluster. So, I thought to start with an elementary step. In this simple step-by-step tutorial, I’ll demonstrate how to deploy a Node.js app in Red Hat Openshift. There are many ways of doing it. I’ll use the source-to-image (S2I) feature of Red Hat Openshift in this article.

What is source-to-image (S2I) from Red hat OpenShift?

Let’s check directly from Openshift documentation:

Source-to-Image (S2I) is a framework that makes it easy to write images that take application source code as an input and produce a new image that runs the assembled application as output.

https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html

Basically. S2I framework allows us to create Docker container images from the source code without writing a single line of code. The following image from Red Hat explains the concepts beautifully.

Red Hat Openshift source-to-image (S2I)
Red Hat Openshift source-to-image (S2I)

It’s worth noting that the S2I utility is a separate open-source module that we can use even outside Red Hat OpenShift. It’s available on Github: https://github.com/openshift/source-to-image.

In this article, I will use the source-to-image (S2I) feature to deploy a Node.js app in the Red Hat Openshift local cluster.

Prerequisite

Build Node.js application

Sometimes back, I wrote a blog on how to deploy a Node.js application in a vanilla Kubernetes cluster. I’ll use the same Node.js app to deploy in Openshift. Hence, I won’t lengthen the article by repeating the same steps. You can go through the steps mentioned in the Build Node.js application section.

For better maintenance, I have cloned the code & other fields to a new repo, which is available in the https://github.com/msadrud/openshift-nodejs-hello-world repository.

Deploy the Node.js app

The time needed: 20 minutes.

  • Start the Red Hat Openshift Cluster.

I am using a locally installed Red Hat Openshift cluster. So, I’ll manually start the cluster. You can skip this step if you are using an already running cluster. Ensure that the oc command line utility is set up.

NOTE: Refer here if you are not sure how to start your local cluster or setup oc command line utility.

  • Create a new project using the oc command

Now, we’ll use the oc command to create a new project in the Openshift cluster. Issue the following command.

At this point, if we open the Openshift web console and click on the Topology, we won’t see any resource. A page similar to the following snippet will be visible.

node.js red hat openshift source-to-image s2i new Project
Red Hat OpenShift New Project

We can deploy the node.js app using either the GUI or the command line. We’ll do both, but first, let’s try the GUI.

GUI-based steps to deploy a Node.js app in Red Hat Openshift using source-to-image (S2I) :

  • Click on the +Add menu item from the left pen and then select the Import from Git option on the page that opens on the right.
node.js red hat openshift source-to-image s2i Import from GIT

  • Provide the Git repository URL. It’ll validate the repository artifacts and show you some options below with auto-populated values. You can always go through each of those and change them to suit your need. However, in this POC, we’ll keep everything default. Ensure you have not unchecked the Create a route to the Application option; it should remain checked as it is by default. Click on Create button.
node.js red hat openshift source-to-image s2i Start the build process

  • After a while, you will notice that the Topology window is now populated with one Deployment resource. Our pod is now running!!

  • Click on the little Open URL icon towards the top-right corner(red-marked in the snippet), and a new tab in your web browser will open up with the response from the Node.js app we created.

  • Hurray!! We just ran our Node.js app 🙂

Let’s check the different objects that OpenShift S2I process created in this process:

Tip

The result of oc get pods command is interesting. It shows two pods. One of them is in running state which is our actual application pod. But, there is also another pod, with -build suffix, in completed state. What is the significance this other pod?

Well, the build process took the source code of our node.js application and combined it with the builder image to create a custom image of the application. This process used the build pod to create this custom container image.

CLI-based steps to deploy a Node.js app in Red Hat Openshift using source-to-image (S2I) :

Another simple way to deploy the app is to use the powerful oc command line utility. To distinguish this POC from GUI based method, I have updated the index.js file with a new message, “Hello World from k8s cli-build!”. Now, let’s proceed:

  • Let’s create a new project mynodecliproject
  • Create the new application openshift-nodejs-hello-world-cli
  • Unlike the GUI method, OpenShift does not create route objects. We’ll need to expose the service object using the following command:
  • Now, let’s describe the route and figure out the URL of the application from the Requested Host field below:
  • Copy the value of the host and test it from the browser. It’ll render the response from our node.js application.
S2I Build from CLI
S2I Build from CLI

What are the components created by the S2I build process?

Now, a bit of theory. Let’s look at the components created by the above S2I build process. Applications in OpenShift don’t get deployed in a monolithic way. It consists of several different components that work together to maintain the application lifecycle. PFB a list of the important components:

  • Image
  • Image Streams
  • Pods
  • Build
  • BuildConfig
  • Deployment
  • Services
  • Routes

In OpenShift For Developers book, the distinguished authors very nicely described the application components that OpenShift creates and, amongst them, which components are of native Kubernetes and which are of OpenShift. Let’s take a look.

Figure 2-3 from OpenShift For Developers book

Image

When OpenShift deploys an application using the S2I framework, it creates an image of the application using its source code and a builder image. An S2I builder image is a basic container image supporting a language created following the S2I specification. There are many S2I builder images for different languages, for example, .Net, Java, Node.js, Perl, etc. In this tutorial, we are using a Node.js builder image. However, as we are using the wizard of OpenShift itself, we don’t have to choose the builder image ourselves; instead, OpenShift will take care of it automatically.

ImageStream

One crucial point to understand about ImageStream is that it does not contain the actual image. The actual image is stored in either the in-built image registry of the OCP platform or an external image registry. We can consider ImageStream as an abstraction layer on top of the actual image registry.
When an object configuration (E.g., Build or Deployment) wants to refer to an image, it points to the image stream and not to the image registry directly. In execution time, OCP queries the actual registry behind ImageStream to locate and use the actual image.

Pod

Pods are the smallest deployable units of computing that one can create and manage in Kubernetes. A pod generally contains one container. However, having more than one container in a single pod is possible. The container(s) inside the pod share storage and network resources. Pods are ephemeral. However, pods can be configured to run the stateful applications as well.

Build

Generally, Build is a process that takes specific inputs and creates the desired artifact. In the OCP context, the Build process takes the source code and builder image to create the custom application image. The instruction for the build process is stored as BuildConfig.

The image building process starts a container from the builder image, downloads and integrates the application source into the builder image container, runs the assemble script from the builder image, and saves the final custom container image for the provided application into the image registry.

BuildConfig

The BuildConfig is an OpenShift custom resource that defines a single build definition. It contains all the information needed to build an application image from a specified source; for example, how the Build is triggered, build strategies (Docker, Source, Custom, Pipeline), the name of the builder image, the name of the resultant image, where to store that image, etc. A BuildConfig is automatically created as part of the build process when using the S2I build process.

Deployment

As described clearly in the OCP documentation, the Deployment object describes the desired state of a particular application component as a pod template. A deployment is an object in OCP, and it is enabled by a native K8S API object called ReplicaSet. ReplicaSet in K8S ensures the configured number of pod replicas are running at any time. Simply put, Deployments in OpenShift create replica sets that, in turn, orchestrate the pod life cycle.

Service

Service works as an internal load balancer/Proxy that receives the traffic and sends it to one or more pods behind. We can add or remove pods as required without impacting the service. Service distributes the traffic to its associated and available pods seamlessly. By default, OpenShift assigns a cluster internal IP to the service, which is not accessible from outside the cluster.

Route

As we just learned, a service is visible only inside the cluster. So, we can consume the application through the service layer only from inside the cluster. A route exposes a service to the external world using HTTP or HTTPS based on our preference. The Route is accessible in the outer world because a public DNS entry is created.

Deploy a new change/update in the existing source code

Thus far, we built an image using S2I and then deployed that in OpenShift. Now, let’s see how we can deploy any change in the source code.

We’ll explore both GUI-based and CLI-based approaches

Redeploy the updated code using GUI

We’ll update the code in the index.js file in the git repository. We’ll update the existing response string to “Hello World from OpenShift!” in line number 6.

Let’s return to the OpneShift web console and traverse to Builds->BuildConfigs. We’ll click on the triple vertical dot on the right and then click on the Start build menu item [Refer to the picture below]

OpenShift S2I - Redeploy updated code
OpenShift S2I – Redeploy updated code

The build process will start; give it a while to complete the process. After that, switch to Developer mode, and click on the Topology menu item. You’ll notice that the Topology window is now populated with an updated Deployment resource. Our new pod is now running!!

OpneShift S2I - New Pod with updated code
OpneShift S2I – New Pod with updated code

Click on the little arrow icon with the tooltip “Open URL.”; it’ll open a new browser tab and display the updated message.

OpenShift S2I - Updated Response Message
OpenShift S2I – Updated Response Message

Now, by executing the oc get all commands, let’s see what the resources/objects newly created in our cluster are:

  • We can see that the OpenShift created a new build pod.
  • The old application pod is no more there; instead, we have a new pod that runs the updated code.
  • OpenShift created a new replica set for the new deployment that we did.
  • There is a new build as well.
  • The image stream is pointing to the latest version of the image.

Redeploy the updated code using CLI

To distinguish our POC from the GUI-based method, let’s update the code in the index.js file in the git repository. We’ll update the existing response string to “Hello World from OpenShift cli-build!” in line number 6. We’ll execute the following command:

Now, let’s refresh the browser and see the result:

OpenShift S2I CLI build - Updated Response Message
OpenShift S2I CLI build – Updated Response Message

Conclusion

Through this article, I wanted to document my learning and observations (for future reference) and share the same with you.

In my learning process, I went through many articles on the internet and also scanned through books. I have listed those below, and I hope I didn’t miss any!

30

No Responses

Write a response

This site uses Akismet to reduce spam. Learn how your comment data is processed.