/unikernels

State of the art for unikernels

MIT LicenseMIT

State of the art for Unikernels

Unikernels are specialised, single address space machine images constructed by using library operating systems -- Wikipedia

Unikernels are library operating systems that provide the ability to run applications within a protected, single-address space environment. Such operating systems delegate the management of physical resources to an underlying hypervisor, which is treated as a trusted platform. Due to the absence of a large number of software components that commonly exist in monolithic operating systems, Unikernels can provide a more stable, small and secure environment in comparison. Currently, there are two main approaches:

  1. Clean slate, where a new minimal kernel is written using a high-level programming language
  2. Strip-down, where an existing kernel implementation is modified accordingly to remove unnecessary components to reduce both complexity and overhead.

Unlike monolithic operating systems such as Linux that permit libraries to be modified, recompiled, shared and dynamically linked, Unikernels typically rely on static linking to combine the application code and associated libraries with the kernel into an immutable, single-purpose virtual appliance and may therefore be seen to be more trustworthy. Other Unikernel approaches implement the ability to use shared libraries at run-time, which could in some circumstances be seen to present a security risk, but provide more portability for running Linux-based applications.

TL;DR

Oct 2023 (is this out of date? Send a PR)

Despite a lot of hype around 2015-2016, Unikernels did not gain much popularity, and have not been adopted by practitioners as software containers and related orchestration frameworks such as Docker and Kubernetes respectively.

The main blockers for a wider adoption of unikernels appear to be:

  • Compatibility with existing code and difficulty in porting applications as this requires specialised skills to port standard libraries or modify applications to run on a newly developed kernel
  • Lack of adequate system debugging capabilities and instrumentation tools which may be useful for developers
  • Difficulty in integrating monitoring, logging, and instrumentation tools that gather information about running applications although this may have been achieved in some examples such as NanoOS
  • Currently, there is no universal or general-purpose approach as each Unikernel supports a unique programming language run-times and may provide different functional abstractions
  • Lack of standardisation similar to Linux or Docker
  • Running VMs means applications cannot share some resources (unused RAM) like they can in Linux containers

A few thoughts (correct me):

  • Security: Unikernels provide smaller attack surfaces compared to Unix-like operating systems. This is one of the strongest arguments for adopting Unikernels. However, the counter argument is that Unikernels have a focused attack surface, which allow attackers to focus on a small set of functionality to attack although this is practically very difficult to achieve. Moreover, Unikernels present a minimal interface that is determined by the needs of the application that is linked with the kernel. Security does not necessarily make the ability to debug the application and kernel difficult but more adequate debugging tools are needed. There has been some progress in improving the debugging capabilities of paravirtualised Unikernels written in C that run Xen hypervisor for example, see the Duster project for more details.
  • Lightweight: One strong argument of adopting Unikernels is that they have a small memory footprint, and are small in size due to the lack of software components that commonly exist in Linux which increase overhead. Moreover, this permits Unikernels to be deployed onto virtualisation platforms relatively faster than Linux virtual machines. Memory resources may have to be pre-allocated for the virtual machine and therefore memory may not be shared with other applications running in isolated environments as the case in Linux containers.
  • Performance: While a simple kernel without the overhead of syscall switch does increase the performance of some operations, it's not clear how well that applies to applications for which the syscalls aren't bottlecks. Besides, the high performance comes at a cost, so will only be an acceptable tradeoff for a subset of applications.
  • Debugging/Monitoring: With the advent of eBPF, the visibility into the kernel has increased dramatically, so the standard have risen. Unikernels would need to provide a viable alternative for massive adoption to happen. However, it is useful to note that as Unikernels run as single-address space environments, the notion of kernel and user spaces do not exist and therefore technologies such as eBPF may not be tailored towards Unikernels.
  • Scheduling: Software containers now have a few options for scheduling such as Kubernetes, Nomad, etc. Scheduling virtual machines, however, with something like OpenStack would require some improvement to provide easier and adequate support for deploying virtual machines quickly in a similar manner to container-related solutions. This could be alleviated with things like Firecracker that can integrate with Kubernetes, but these haven't exactly blown up in popularity either.
  • Compatibility: Software containers provide the ability to package existing software applications and associated libraries which may be needed for their execution without modification. Unikernels require compiling the kernel together with the application. There are some solutions that can produce a Linux binary for debugging and a kernel image for production. Keeping the Unikernel (mostly) Linux-compatible is possible, but requires some gluecode.

Currently, the only two with commercial support I could find are Unikraft and NanoOS. If you're looking to learn to make your own, check out the StardustOS project which is used to support the teaching and research activities at the University of St Andrews. This project actively maintains several Unikernel implementations including stardust which is written completely in C and stardust-oxide which is written in Rust, along with a minimal kernel for Xen that's easy to browse through.

Unikernels

Project language src started last commit status
Unikraft C https://github.com/unikraft/unikraft 2017 recent active
NanoOS C https://github.com/nanovms/nanos 2017 recent active
Mirage OS OCaml https://github.com/mirage/mirage 2014 recent active
OSv C https://github.com/cloudius-systems/osv 2012 recent active
RustyHermit Rust https://github.com/hermitcore/rusty-hermit 2017 recent active
HermiTux C https://github.com/ssrg-vt/hermitux 2017 recent active
Kontain C https://github.com/kontainapp/km 2018 recent active
StardustOS C, Rust https://stardustos.gitbook.io/stardust/ 2019 2022 dead
Rumprun C https://github.com/rumpkernel/rumprun 2014 2020 dead
HermitCore C https://github.com/hermitcore/libhermit 2015 2021 superseded
Click OS C++ https://github.com/sysml/clickos 2007 2014 dead
Clive Go https://github.com/fjballest/clive 2015 2016 dead
HaLVM Haskell https://github.com/GaloisInc/HaLVM 2010 2018 dead
GUK C https://github.com/Leonidas-from-XIV/guestvm-guk 2011 dead
runtime.js C++, JS https://github.com/runtimejs/runtime 2014 2019 dead
Include OS C++ https://github.com/includeos/IncludeOS dead
LING dead
Drawbridge ???

Toolchains

Project language src started last commit status
Unik Go https://github.com/solo-io/unik 2016 2019 dead?

Various related

Project description status
Qubes OS everything is a VM active
gVisor userspace Kernel active
Firecracker micro VMs (using KVM) active

Links

Papers

Books

Talks

Articles

Linux