In November, unikernels took to the stage at DockerCon EU in Barcelona! As part of the Cool Hacks session in the closing keynote, Anil Madhavapeddy (MirageOS project lead), showed how unikernels can be treated as any other container. He first used Docker to build a unikernel microservice and then followed up by deploying a real web application with database, webserver and PHP code all running as distinct unikernel microservices built using Rump Kernels. Docker managed the unikernels just like Linux containers but without needing to deploy a traditional operating system!
This kind of integration helps put unikernels into the hands of developers everywhere and combines the familiar tooling and real-world workflows of the container ecosystem with the improved security, efficiency and specialization of unikernels. We’ll finish off this post with details of how you can get involved — but first, before we go into Anil’s demonstration in more detail, some background about why unikernels matter, and why it makes sense to use Docker this way.
As companies have moved to using the cloud, there’s been a growing trend towards single-purpose machine images, but it’s clear that there is significant room for improvement. At present, every VM has to host a copy of the OS on which the application runs, especially where strong isolation is required.
These VM-hosted applications are also affected by OS vulnerabilities, including exploits that have no relation to applications’ day-to-day functions. For example, USB drivers — present in an OS but irrelevant to cloud deployments — have had multiple vulnerabilities which allow arbitrary code execution. Patching such code creates a needless maintenance burden.
Unikernels take a different approach: application code is linked against only the OS components it specifically requires to produce a specialised, single address space machine image — thus eliminating unnecessary code. Built using ‘library operating system’ technology, unikernels provide many benefits compared to a traditional OS, including:
- Improved security properties — as unikernels contain no unnecessary code deployed, the application’s attack surface is dramatically reduced.
- Smaller footprints — unikernel code bases are typically several orders of magnitude smaller than their traditional equivalents and they can be managed much more easily.
- Fine-grained optimization — as unikernels are constructed through a coherent compiler tool-chain, whole-system optimization can be carried out across device drivers and application logic, potentially improving specialisation further.
- Fast boot times — as unikernels can boot in less than a second, provisioning can become highly dynamic.
These benefits are particularly relevant to microservices and the developing concept of ‘immutable infrastructure’ — where VMs are treated as disposable artifacts and can be regularly re-provisioned solely from version-controlled code. Modifying such VMs directly isn’t permitted: all changes must be made to the source code itself.
Unikernels naturally lend themselves to both the microservice architecture and the concept of immutable infrastructure: both source code and generated binary are compact enough to be easily version-controlled. If the traditional stack has allowed us to move towards microservices, then unikernels will move us towards the world of immutable nanoservices.
Although unikernels provide a path, there are significant challenges to their adoption in production settings. The unikernel ecosystem is only just taking off, and this new technology needs to fit in with existing workflows and tooling.
Linux containers have allowed developers to move much more quickly towards microservices by allowing a traditional OS to provide functionality to multiple ‘containerised’ applications sitting above it. Those containers remain distinct and thus can be independently replaced or modified, a core piece of the microservices architectural pattern.
Although containerization technology has been available for some time, there’s been a recent and rapid increase in the pace of adoption. The last few years have seen a proliferation of tools that make it easier to use containers at scale, including registries of ready-made images, tools for orchestration, and much more. Led and fostered by Docker, this has produced a vibrant, open and growing ecosystem, which is helping improve everyone’s development workflows.
With an increasing number of supported tools and infrastructure, it’s become clear that the ecosystem is about much more than just Linux containers themselves. Can unikernels fit in this ecosystem? If so, where would unikernels sit in relation to containers?
Containers and unikernels actually sit on a continuum. On the one hand, we have the traditional method of placing a full OS stack in a VM with a single application on top. A natural next step is to use containers which run on top of a single OS, giving better resource usage and allowing each application to be more self-contained. When viewed this way, unikernels are just another step on this path and can be thought of as extreme, self-contained applications. The challenge is to make unikernels as easy to use as containers have become today.
The obvious first step in addressing that challenge is to integrate unikernels with the existing container infrastructure, specifically the Docker tools and ecosystem. This helps us to get unikernels into the hands of developers everywhere, with a widely used and understood packaging model and runtime framework, effectively by making unikernels just another type of container.
It also unlocks the entire container ecosystem of tools for use with unikernels, including orchestration and whatever else may be around the corner. Adoption of existing toolchains will accelerate the progress of unikernels and also demonstrates the flexibility and breadth of the Docker ecosystem. By using Docker to abstract away the complexity of the underlying OS, a developer can choose how they "containerize" their application, whether they target a traditional Linux container, or a new unikernel ‘container’.
It is exactly these first steps enabling developers to build and run real-world unikernel microservices, using existing Docker tools, which Anil demonstrated at DockerCon EU today!
First he used Docker to build a unikernel microservice, and then he ran a cluster of unikernels to deploy a real web application with database, webserver and PHP code. The whole build system is wrapped in an easy-to-use Dockerfile and each microservice is turned into a specialised unikernel. Those unikernels run in their own KVM virtual machine with hardware protection. Docker manages the unikernel containers just like Linux containers, including networking!
This early work makes unikernels a usable target for a Docker deployment! Since unikernels can now be managed by Docker, it can bring all the benefits of the existing ecosystem to the orchestration and management of unikernels.
The demo consisted of using the typical components found in a LAMP stack, specifically Nginx, MySQL and PHP. These unmodified, off-the-shelf components were built using the Docker toolchain but instead of the typical OS they were built as unikernels! A cluster of these unikernels was created where each of them was specialized for the particular app they were running. Watch the screencast below for more details!
The demo described here is just the beginning. There are many implementations of unikernels and there’s plenty of work ahead to ensure they can all reap the benefits of integration, as well as improving Docker itself to make the most of these new technologies. Look over the collection of unikernel projects and contribute your experiences to this blog!