📦 Cloud Containerisation is great, but have you heard of 🥜 Unikernels?

Joshua Ben-Tzion Quek
9 min readOct 27, 2021

--

Source: https://dev.to/bondijois/understanding-unikernels-the-future-of-cloud-computing-probably-57a3

Recently, I have been doing some on-and-off research on the kind of technology will eventually succeed cloud containerization technologies like Docker or Kubernetes. Over the past few years, there have been a rise in the digital paradigm of serverless cloud technologies as well as containerisation cloud technologies, as opposed to traditional compute VMs (virtual machines), when it comes to implementing “next-gen digital” architecture on the cloud.

Honestly, I love the fact that cloud containerisation allows for provider-agnostic deployments, which I have covered in my previous article - https://medium.com/digital-coe/strategizing-for-multi-cloud-agnosticity-4a000c5425aa

In this article, I want to propose something that could possibly either be an alternative to both serverless tech and containerisation tech - Unikernels!

How Unikernels differ from Containers and Traditional VMs. Source: https://sudhakar-dharmaraju.medium.com/goodbye-linux-the-next-os-317801a5c0ba

Imagine something that takes up less CPU and memory than both containers or traditional VMs , while not needing any additional “cluster mesh” layer software like Kubernetes and Docker or “Host OS” layer like Windows, Ubuntu, RHEL, CentOS, etc to configure and maintain. That is essentially what a Unikernel is!

Just take your NodeJS, Python, Java or Golang application code and convert it into a machine image (i.e. AWS AMI). Using that image, deploy that as a unikernel compute instance (i.e. AWS EC2)!

Done! 👍🏼

Wait, isn’t that just a Virtual Machine (VM)? Yes and no. From the earlier screenshot as well as the one below, we can see that unikernels essentially are your actual application code without ahost Operating System (…well, sort of), rather than it needing a complete host Operating System like Ubuntu, Windows, CentOS or RHEL to function:

Source: https://www.mdpi.com/2227-9717/9/2/351/pdf

A separate academic study on unikernels also mentions that:

“Unikernels exceed containers in terms of pure speed and response time, firmly surpassing them for single core performance on a Type I hypervisor. In our evaluations, Java and Python unikernels performed 16% better than their respective containers for a REST service stress test, and Go (Golang) even performed 38% better.”
(Source: https://www.researchgate.net/publication/329563819_Unikernels_vs_Containers_An_In-Depth_Benchmarking_Study_in_the_Context_of_Microservice_Applications)

In short, it suggests that your app deployed on the cloud will generally cost less and perform better when deployed as a unikernel than if it were to be deployed as a container.

If you are interested more in the benefits and the technicalities behind them, you can read more here: https://www.section.io/engineering-education/why-unikernels-may-soon-replace-docker/

Ok, so that was lot of theory on why unikernels might be the “next big thing” after containers ( …or I might be wrong haha!), so that leads us to the next question - how can we PRACTICALLY implement unikernels?

🤲🏻 Try it yourself here

Wait no further - I have created a hands-on “try-it-yourself” tutorial for you to deploy your first unikernel on the cloud (AWS)!

…All you need is your laptop and an internet connection.

This tutorial uses the open-sourced OPS Unikernel Framework by NanoVMs https://nanovms.gitbook.io/ops/getting_started. In my opinion, their support team on Github is quite responsive whenever you run into issues trying to deploy your unikernel.

Step 1: Installation

Install the OPS Framework. I am using MacOS, so curl works by default on my unix-based command line. Open your command prompt/ terminal and run the command

curl https://ops.city/get.sh -sSfL | sh

Source: https://nanovms.gitbook.io/ops/getting_started

If you are using MacOS Big Sur, you will have to enable code-signing:

Source: https://www.arthurkoziel.com/qemu-on-macos-big-sur/

Since we will be deploying to AWS, ensure that you have the AWS command line interface installed too.

Download the AWS CLI: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-mac.html

Source: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-mac.html

Login to AWS on the AWS CLI to allow for your laptop/computer to have programmatic access to your AWS account: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config

Source: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config

Before we move on to Step 2, also ensure that you have NodeJS installed - https://nodejs.org/en/download/. This is because the sample app that you will be deploying later on will be a NodeJS webserver.

Source: https://nodejs.org/en/download/

Great! Once this is done, let’s proceed to Step 2.

Step 2: Running a sample NodeJS app as a unikernel locally

Once you have successfully completed Step 1, head over to the repo that I have configured for this tutorial https://github.com/joshuaquek/expressjs-ops-unikernel and clone it to your local computer:

Source: https://github.com/joshuaquek/expressjs-ops-unikernel

From the codebase, you can see that it is a simple nodejs ExpressJS server that has two API endpoints / and /test_message :

A simple ExpressJS web server on NodeJS with two endpoints

Once the repo has been cloned down, run npm install to ensure that all of the libraries get installed.

Running `npm install` to install your nodejs dependencies

You can test your nodejs app locally by running npm start for a normal start or you can run npm run dev, if you wish to have your code hot-reloading every time you save a file in the project.

You should then be able to view your running app via http://127.0.0.1:80/ or simply http://localhost/

You can now visit http://127.0.0.1:80 on Chrome to see your locally running nodejs app
Visiting the URL http://127.0.0.1:80 on Chrome browser

Next you can test that the OPS Framework is able to compile/build your nodejs app into a unikernel image and then run that image as an instance locally by running npm run local:deploy

Running the command `npm run local:deploy`

You can then revisit http://127.0.0.1:80 to see your nodejs code now compiled into a unikernel

You should see the same screen as before!

Step 3: Deploy the Unikernel to AWS

Good job! Now that you have ensured that your code works locally, lets deploy it to the cloud on AWS.

Assuming that you have successfully competed Steps 1 and 2, run the command npm run aws:upload - the OPS Framework will then compile/build your codebase into a unikernel image before uploading it to AWS.

Running the command `npm run aws:upload`

You will be able to view the uploaded unikernel image under the AWS web console > EC2 > Images > AMIs

You will find your newly minted unikernel image under EC2 > Images > AMIs

Using this image, one would be able to launch an EC2 instance by pressing the Launch button and selecting the various config options before your unikernel gets deployed.

However, you won’t need to do that. The OPS Framework automates this process - run npm run aws:deploy in your command line terminal.

Running the command `npm run aws:deploy`

Done! 👍🏼

Head over to EC2 > Instances and you will see that your unikernel has been deployed as an EC2 instance:

Using the EC2 AMI image, running `npm run aws:deploy` then uses OPS to automate the EC2 deployment

In the screenshot above, you can see that the instance deployed has a public IP address of 13.250.107.36 . The instance you deploy would have a different public IP from this example.

For my case, I will then be able to see my deployed app at http://13.250.107.36 (You can enforce HTTPS/SSL separately using AWS Route53, but this will not be the focus of this tutorial)

If you can see this message, it means that you have successfully deployed your first unikernel!

You can also try hitting the other API endpoint of this ExpressJS server /test_message , which should then show the appropriate response:

The other API endpoint that is part of this nodejs app codebase (covered earlier on)

Great work! 👏🏼

Wasn’t that difficult, right? Plus there is no need to have an additional “containerisation cluster” layer between your NodeJS app and your actual compute VM.

Do note that this tutorial deploys your unikernel to a public subnet, and it is advisable to deploy it to a private subnet before fronting it with a HTTP/HTTPS load balancer for production deployments.

You can have more granular control over where your app gets deployed to using the config.json file within the codebase:

More info on the `config.json` file can be found at https://nanovms.gitbook.io/ops/configuration#sample
I have also included an example `config.json` here: https://github.com/joshuaquek/expressjs-ops-unikernel#configuration-file

If you wish to peek at your app logs, you can simply do so here in the EC2 Dashboard by either accessing the “system log” or the “instance screenshot” options:

Method 1: EC2 > Instances > Your Instance > Monitor and troubleshoot > Get system log
Method 1: The “system log”
Method 2: EC2 > Instances > Your Instance > Monitor and troubleshoot > Get instance screenshot
Method 2: The “ instance screenshot”

One would not need to have a separately deployed management tool like Kube Dashboard which connects to a underlying control plane (i.e. Kubernetes or Docker Swarm), which consumes additional CPU and memory bandwidth from your underlying compute hardware or VMs.

This is because for Unikernels, that management layer is simply the AWS EC2 Dashboard!

🔐 Security of Unikernels

Security wise, unikernels have a very minimal attack surface, if one were to do a few quick searches on google:

Source: https://www.section.io/engineering-education/why-unikernels-may-soon-replace-docker/
Security consideration for OPS Framework. Source: https://dev.to/bondijois/understanding-unikernels-the-future-of-cloud-computing-probably-57a3

Here is another security-related writeup by the creators of the OPS Framework (NanoVMs) themselves:

Source: https://nanovms.com/dev/tutorials/assessing-unikernel-security

Just to reiterate once more, if one decides to use unikernels for production purposes, it would be advisable from an architectural perspective to deploy your unikernel instances on a private subnet, and then route traffic to these private instances using a HTTP/HTTPS load balancer.

Conclusion

While traditional VMs, serverless technologies and cloud containerisation technologies are here to stay due to tech lock-in for many organisations, Unikernels could be the new underdog in the cloud compute technology space. This is mainly due to it being:

  • Open source, which drives adoption! In my opinion, the day that the Ops Framework becomes closed source, that is when adoption will drop and this framework will become an “only-if” kind of tech. The best frameworks which the largest audiences I have seen out there are all open-sourced - ReactJS, Kubernetes, Flask, Django, Pytorch, Docker, NodeJS, Angular, Typescript, NextJS, Bootstrap, Vue, Lodash, Webpack, etc… and the list goes on.
  • Easy to implement, from the simple tutorial above
  • Easy to maintain for those who are already familiar with deploying simple EC2 instances, where one does not need a whole team of Kubernetes or Docker specialists to manage the underlying “cluster mesh”
  • Better performance for the same underlying hardware compute cost
  • Cloud-agnostic, unlike serverless technologies which lock you into a single cloud provider. However, serverless technologies have the advantage of having that “pay per use” model
  • Easy to scale. For AWS EC2, one can simply use an EC2 Auto Scaling group
  • Secure, with a low attack surface
  • One can also convert Docker container images into unikernels/use them as base images for your unikernels - https://nanovms.gitbook.io/ops/packages#create-a-package-from-docker . I personally haven’t explored this yet, but will be taking a deeper look at it soon 😀

If you have enjoyed this article, please give it a few claps, share it with someone who might like it and remember to subscribe! Thank you!

--

--