Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Run asynchronous tasks in a new Kubernetes pod with NodeJS.

Sign upSign InSign upSign InAlexandre OliveFollowITNEXT--ListenShareWhen you start creating APIs as a junior developer, you build everything synchronously. You don’t think in advance that the data in production is much bigger, that the forEach on your test data will behave differently on a million lines. If you’re lucky, everything breaks when you release your code. If you’re unlucky, it will take days of users complaining of random crashes before you find the culprit piece of code that overloads your API.I know that because I’ve been through it enough to learn the lesson — especially when your company at the time has a three-week delay on release, but that’s another subject. I still get “javascript heap out of memory” nightmares occasionally.Then, you grow as a developer. You learn about asynchronous design with message queues and workers. Your user-facing APIs don’t have to crash when too many resource-intensive tasks are triggered simultaneously.Thanks to my current job, I discovered the next level of asynchronous setup we will build in the article: how to use new Kubernetes pods to do resource-intensive tasks asynchronously outside the current API. The goal is to prevent overloading the user-facing endpoint and cause slowness in your application.This setup will be overkill for most applications; it depends on your use cases. For example, you might need it if you want to run that process in a particular kind of node, like a GPU-optimized one.If you want to read more about the architecture around my company’s use case using this system design, check out the link below.alexandreolive.medium.comIf I wanted to build the whole system design production ready in one article, it would be a thirty-minute read minimum, with too many concepts to introduce simultaneously.So, in this article, we will set up a Kubernetes cluster locally, in which we will launch pods from a NodeJS API. The pods will be Docker containers running NodeJS scripts that will wait a fixed amount of time to mimic a lengthy task and then call the API back to update the task’s status.It might be scary when I say it like that, but you don’t need advanced knowledge of those subjects to follow along with me.The API is purposely outside of the cluster in this schema, as I don’t want to get into Kubernetes connectivity with services or ingress just yet.There also is no queue system on purpose to make it easier to write in a single article. In a typical setup, the API will not launch the pod itself; it will add a message in a queue, and the queue’s worker will launch the new pod.I will write a follow-up article where I implement the API inside Kubernetes. If you’re a YAML enjoyer, Kubernetes initiated, and want production-ready implementation; it will be made for you. (I’ll update this post with the link once it’s online).Running a Kubernetes cluster in the cloud costs money, and I don’t know you, but I don’t like to spend money. Thanks to the awesome creators of Kubernetes, you can run your own Kubernetes cluster locally with Minikube.The installation process is super easy. Make sure you select the correct operating system and architecture (you also need Docker installed).Stop at the “3 — Interact with your cluster” step. You are good to go if you can run the command kubectl get po.That’s it for this article; it’s that easy. We got the Kubernetes cluster setup out of the way; we can now get to the actual coding.Before getting into the API creation, we must build a Docker container as our resource-intensive task.It will be composed of 2 files: first will be a javascript file that runs the actual process, and the other will be the Dockerfile to create the docker container.Let’s break it down.To build a container, we need a Dockerfile. This simple Dockerfile copies and runs the javascript file we created inside the container made of a node:20-alpine image.If you want to use your image when we launch it in the Kubernetes pod, you can build and push this Dockerfile by following the readme.md file I wrote here. If not, I’ll provide a working Docker image of the process later in the article.Let’s get to the good part: we want to launch a pod from an API.We will use ExpressJS as it’s lightweight, easy to use, and easy to understand.Let’s initiate a new project with npm initinside a new folder. You can press enter for every question; it does not matter for our test.You can add "type": "module" inside the package.json to use module type imports. That’s how it’s done nowadays; CommonJS days are coming to END! Where are you hiding developers still using CommonJS ?! Sorry, I lost control; let’s get back to the tutorial.You must also add a new script in the package.json to start the API (if you are using an older node version, remove — watch).We need four packages for our API to work:We can install them with:Next to your package.json, you can create a file called index.mjs. You can add the following code inside. I won’t dive into it, as it’s just the default setup for Express. Here is a get-started-with-express article if you want.We will need three endpoints:To connect to the cluster we will use the @kubernetes/client-node library.If you have only minikube installed locally, using kc.loadFromDefault() is enough to connect—no need to pass a cluster configuration. The k8sApi variable will allow us to access functions that interact with the cluster.Alright, we’ve reached the most complicated part of the article. Before jumping into the code, let’s list all the information we need to launch our pod.Here, you can find the code for the function createNewPodthat will create the pod — who would have thought with that name?We call the function createNamespacePod, with the first parameter being the namespace. Namespaces are Kubernetes way of isolating groups of resources; we use the default one here to keep it simple.Since our API is running outside of the Kubernetes cluster, we need to add a host alias for our pods to be able to call the API from inside the cluster. If we tried to call localhost from inside the pod, it would be Minikube’s localhost and not our local machine.To find your machine's IP address, you can run minikube ssh grep host.minikube.internal /etc/hosts | cut -f1 and replace mine I set in the code.Finally, let’s wrap our createNewPod function in an Express endpoint definition to be able to call it.We also create a JSON file to store the task's status on the file system. The webhook will update it when the asynchronous process ends. In an actual setup, this file would be a database.This part was getting long, and I thought everyone who reached this point needed a little “cat” break — isn’t he cute?We are now at a point where we can create a pod through the API. But before we go and try it out, I’d like first to implement the endpoint to retrieve the pod's status. It’s straightforward and will help us check that our pod creation worked without running Kubernetes CLI commands.First, we retrieve the pod in the cluster using the pod name, which is the task ID (remember Elon Musk’s child from earlier ?) that we get from the URL param. Using the same name, we retrieve our JSON file created when we started the pod and send back both information as the API result.Okay, let’s try it out now. Launch your API with npm run start and use your favorite API testing tool to do a simple POST on /start. For me, this tool is still Postman. It should return our taskId, namespace, and uid. Which means it started successfully.If you take the taskIdfrom the body’s response and do a GET on /:taskIdWe get our status entered manually, plus the technical pod status information. Hell yeah!The issue is that the process will fail because we have yet to initiate the webhook endpoint.We have a final endpoint to add. The one that the process will call once it’s finished to update our fake JSON database.There’s not much to say here; we’ve seen most of the code used already. We are just using the taskId sent in the body to update the JSON file with a new status.If you retry the process, POST /start to create a new pod and call the GET endpoint to retrieve the task status. You should see it in a running state, but if you wait fifty seconds more it should return the new “finished” status.It lasted just over fifty seconds between the start and end times, as planned.You can find the whole code for this article here.It took a lot of work to set up an asynchronous process like that, and we skipped a lot of mandatory things for an actual production setup.You have to consider that running an asynchronous process means it can fail at many points while running. Networks are not infallible; containers can crash unexpectedly, database writes can fail, and many other issues can occur. Those are problems you must already consider in a traditional application but with many more possible failure points.It must be built from the ground up with excellent error management, retries if anything fails, easily accessible logs, and debugging tools. So, use it cautiously and only if your use case needs it.Despite all those difficulties, it’s a valuable tool to have in your arsenal. I know I loved this concept when I was introduced to it.Thank you for reading until the end. It was a long and technical post that I decided to split into more than one article to make it easier to read. The follow-up will involve running everything in the Kubernetes cluster with multiple nodes to mimic a production environment in Minikube; stay tuned.----ITNEXTSenior Lead Developer 🤓 | Globetrotter 🌍 | Fitness and self-improvement Enthusiast 💪 Love to learn and write about new subjects all the time!Alexandre Oliveinskeepers--11Jacob FerusinITNEXT--8Mahdi MallakiinITNEXT--5Alexandre Oliveinskeepers--2Simeon GrancharovinStackademic--5Alexandre Oliveinskeepers--2Mahdi MallakiinITNEXT--5Mahesh SainiinLevel Up Coding--33Matteo Bianchi--31Shawn.Yang--6HelpStatusAboutCareersBlogPrivacyTermsText to speechTeams



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Run asynchronous tasks in a new Kubernetes pod with NodeJS.

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×