Arguably, the holy grail of cloud deployments is to be able to have images that are (1) performant and efficient, (2) have strong security and isolation, and (3) are easy to use and have a rich tooling environment around them. At present, we can only pick 2 out of the 3:
Virtual machines: provide strong isolation/security, are certainly usable and are the workhorse of cloud deployments BUT they are far from efficient (1GB images or 30 sec boot times anyone?)
Containers : touted as the silver bullet to solve all VM efficiency woes while providing security, they turned out to have a large range of security issues, to the point where, in production, they often get deployed within a VM in order to make them secure.
Unikernels: Certainly efficient (though not always performant, depending on the unikernel project) and with security properties such as a minimal TCB that should in principle provide strong security, past unikernels have floundered in terms of usability: no integration with major orchestration tools, poor to non-existent debugging facilities, little documentation, lack of application/languages support, etc.
In the rest of this blog I’ll show why these unikernels shortcomings where implementation issues rather than fundamental ones, and why Unikraft represents the future of cloud deployments.
Unikernels Have Been Around for a While, Why Now?
In all, if all we want to do is run a 5MB NGINX application in the cloud it makes little sense to be deploying 1GB images consuming huge resources and containing substantial, unneeded lines of code that could lead to vulnerabilities. While the reason behind this status quo is understandable, unikernels, which are specialized VMs tailored to the needs of each application, are a much more logical way forward for cloud deployments. To make this more tangible (and enticing), here a few properties and numbers for Unikraft:
⚡️ Blazingly fast boot/suspend/resume times, in milliseconds
🔥 High performance, up to 2x the throughput of Linux
⏬Low memory consumption, a few MBs for off-the-shelf apps
🗜️ Tiny images, only a few MBs in size
🐇 Low latency
🔐 Minimal TCB: if the app doesn’t need it, it doesn’t get deployed
💪 POSIX compliant: no need to modify your app!
What about the issues with unikernels mentioned above? Neither past security flaws nor poor usability were fundamental problems with unikernels themselves, but rather “features” of individual projects. To be fair, many unikernel projects were research projects maintained, sometimes on spare cycles, by a few people, so it was natural that they came with flaws.
Because these flaws weren’t fundamental, at Unikraft we’ve been hard at work to come up with a unikernel project that fixes these, and in doing so can pull the magic trick of providing efficiency, usability, and security – pick all three! In essence, we can think of Unikraft as having the strong isolation of a VM with the lightweight properties of a process (or worker/isolate).
A Uni What?
There are various definitions floating around, but at its core a unikernel is an extremely specialized virtual machine that only has the code that an application needs to run. By code here I’m referring to the entire stack, from a libc all the way down to operating system functionality such as schedulers, memory allocators and drivers. If the application doesn’t use it, then it doesn’t make it into deployment.
Another commonly cited feature of a unikernel is that they tend to have a single memory address space: unikernels are mostly intended to run on top of a hypervisor (there are of course baremetal use cases but I won’t cover those here) which already provides isolation among tenants/workloads, so having a kernel/user-space separation isn’t strictly required and comes with overheads. Having said that, it would, in principle, be possible to have a unikernel with multiple address spaces.
To best achieve the specialization mentioned above, the unikernel should be based on a modular architecture that allows users building images (or tools that do so) to easily pick needed components – Unikraft takes this to heart, making sure that everything in its code base is set up as a (micro)-library. You can read all the gory details in this (best paper award) document.
So What About Tooling?
In the past, unikernels were obscure beings, penetrable only by those well-versed in the dark art of unikernel hacking. We’ve come a long way since then: with Unikraft, questions to do with tooling are now starting to have standard answers:
- Debugging: debug with gdb, just like you would in Linux
- Monitoring: export stats via Prometheus
- Building: use Unikraft’s kraftkit tool, or the (soon to come) Docker or Packer integrations
- Deployment: supports k8s (coming soon); use standard kubectl and the standard dashboard
- Coding: integration with VSCode (coming soon)
- Upcoming integrations: Knative, serverless.com and others — stay tuned.