TL;DR: In this article, we’re presenting our implementation of serverless computing over kubernetes. You will learn a new way to implement serverless with a lean solution, without the need of using any external dependencies. Upon reading this, you will be able to create your own serverless architecture inside kuberenetes cluster. If your’e looking for a solution for your on-prem environment, stop using remote serverless providers, or just don’t want to pay them for maintainance, this is the place for you.
Serverless computing has become a common term among software development companies. It is a valid architectural solution for teams trying to use cloud services instead of setting up their own servers. Most major cloud platforms have their own solution for this type of development. Azure has Azure Functions, AWS offers AWS Lambda and so on.
A viable solution for this is using the serverless idea, while using kubernetes as the platform to do so.
In this article, I will take you through the thought process behind the decision to use serverless over kubernetes, and of course the implementation. Whether you are a developer looking for a solution for your project, or just an enthusiastic reader looking to learn something new, I believe there’s something here for everyone.
Most developers, both seniors and beginners with some experience, probably had to face the agony of starting up a server just to test their work. These servers need to be maintained, which in most cases can take a lot of time. If you disagree, then you probably are not the person responsible to do this in your company, and trust me, someone’s hair is getting grayer and grayer with every server failure.
Serverless architecture is solving this exact issue. It takes the problem of server maintainance out of the dev team hands, and strips it down to the main functionality needed to execute a specific action. Meaning, I don’t have to wait for a server to “wake up” to execute my code. All I need to do is to send a message using a predefined api (http request in my case) and the server will execute my request. No dependencies, no configurions, no wait time. Easy.
Although severless computing over the cloud is very promising, it does have some limitations. In valid network, we develop a security platform for companies that are using blockchain technology. We allow our clients to analyse their code for potential vulnerabilities. Since we want this to be repeatable, we used AWS’ serverless technology called lambda.
While using lambda we started having some issues scanning some customers’ projects. A quick research uncovered that lambda’s tmp folder had a limit of 500MB. Plus, AWS api gateway had a timeout of 29 seconds. So if our process takes longer than that, tough luck.
This was about the time we started thinking of becoming available on premise as well. We had some clients who were’nt willing to publish their git in our SaaS platform for security reasons, so we had to come up with a solution for them as well.
All of the above led us to start looking into implementing serverless on our own, to be able to maintain the advantages of serverless logic and accommodate them to our needs.
Important thing to note is that this is not a begginer’s guide. The technologies we used here are simply a result of our prior knowledge. The specific tech stack used here is not a constraint. If you’re developing in a different language and/or database, you should be able to implement the same logic.
It’s recommended to familiarize yourself with the following tech stack before jumping into the next section to get a better understanding of the implementation
To implement serverless successfully, we used two different kubernetes deployments running nodejs, RabbitMQ as a queue service, and a MongoDB database instance.
This can be achieved using most of available queue services and NO-SQL databases.
The kubernetes deployments are divided into two. The request pod and the execution pod.
Responsible for sending the requests. Should be stable, and can have many instances. Can use persistent volume.
Connects to the queue service and adds requests to the queue. Other services that wish to run serverless requests, send http requests directly to the request service.
The pod has cache on every job it creates, to monitor the responses using a separate channel in the queue where it functions as the recipient. As soon as it receives notice that a job the service is responsible for is done, it accesses the database and requests data response on the specific job.
When data is successfully received, the pod then sends a response back to the service that created the http request with the requested data.
Responsible for executing requests. Functions as a one-time pod. Dies as soon as it finishes processing the request, and cannot be connected to a persistent volume. Also, the image used to create the pod should be as slim as possible.
The execution pod registers to the queue and waits for a job request. Once it pulls a job with all its data, it executes it. As soon as it finishes, the result of the job is processed on two different channels:
When the execution pod has done its purpose, it dies. The execution service is responsible for creating a new execution pod, that immediately registers to the queue and waits for new jobs.
High-level design of the implementation
Lets go over piece by piece about what needs to be done to successfully implement serverless computing.
We’re using rabbitmq service here since it is very easy to setup. All you have to do is create a service and deployment for rabbitmq.
Here’s a yaml configuration example:
We’re adding a deployment to our kubernetes cluster to function as the request endpoint. The purpose of this endpoint is to receive http requests from other services, create jobs out of these requests and send them to rabbitmq.
We use several npm package dependencies:
Using express library, we receive http requests and add jobs to rabbitmq to execute these requests. We then wait for a response, and once we receive a finished job response with the same job id, we access our database (mongoDB) to extract data from it.
Now we need to add another deployment to our kubernetes cluster to function as the execution endpoint. The purpose of this endpoint is to read jobs directly from rabbitmq, execute them, add results to mongodb and add the result data to a seperate response queue via rabbitmq.
As in the request entity, we use the same package dependencies here:
In this article, we’ve created our own serverless solution over kubernetes. Although many solutions out there solve the same problem, all of them have dependencies over other services that essentially make the deployment process dependant on external services. The solution presented here is lean, and can be implemented with little-to-none external dependencies.
Valid Network’s blockchain security platform provides complete life cycle security for enterprise blockchains from initial development to active deployment and management. Based in Be'er Sheva, Israel, the company’s solutions enable enterprises to innovate with blockchain faster, providing complete visibility and control over their distributed applications and smart contract governance, compliance, and security posture through advanced platform capabilities.
Secure the block with Valid Network.
Learn more: https://valid.network
Valid Data’s real-time and predictive insights are used by Cryptocurrency traders and exchanges, as well as investors and hedge funds, to make better investment and trading decisions, to protect the value of their digital assets, and to capitalize on market opportunities that only Valid Network’s technology can uncover.
Get crypto analysis, insights and updates right to your inbox! Sign up here so you don't miss a single newsletter.