Wednesday, August 29, 2018

What I could not undiscover about Unikernels.

Unikernels http://unikernel.org/ have been around for a while but remain a relatively unknown technology. The core idea of a Unikernel is that it is a specialised operating system that throws away pretty much everything except network and disk drivers and application code, making for a tiny custom operating system that is usually single purpose, and typically claim to be more secure and efficient than traditional operating systems because they have disposed of all the unneeded code and in doing so, also reduced the Unikernels "attack surface".

Let's be clear about one thing - my view of Unikernels is oriented only toward my personal use case for them - that's the context of this post... and there are use cases for Unikernels that do not match my use cases.... I'm just saying so this isn't seen as a criticism of Unikernels, it's just the telling of my journey on that path.

I discovered Unikernels several years ago and took a particular interest in the Rump Kernel http://rumpkernel.org/ which is essentially NetBSD stripped down to little more than the network drivers, the disk drivers and your application code.

The minimal nature of Unikernels is immensely appealing.... tiny operating systems occupying only a handful of megabytes, more secure than traditional operating systems.

I thought I'd arrived early at a technology that was going to explode with popularity because Unikernels made so much damn sense...... security is a big deal and Unikernels were exceptionally secure because it's just an application, there's really nothing you can log in to on a Unikernel.  Contrast this with Linux where most machines are ready and waiting for users to log in, and hackers, once they get access can cause untold damage.

Being first to a new technology that explodes with growth is potentially a big opportunity, so I bet big on Unikernels.  There was work to be done with Unikernels because they were very complex to build and configure, and when I got on board they were not running at all on the cloud platforms.

I invested years building http://www.bootrino.com - software to make it easy to load and run Unikernels on all the major cloud platforms.  That was the gap I saw - making the complex Unikernel technology easy to run in the cloud.  I got my software built and it was fun and I learned a huge amount along the way, but Unikernels didn't explode with popularity, and although the project is still up and running, effectively it is abandoned because it meets no driving market need.

Why didn't Unikernels catch on?

Mainly because of Docker and serverless computing.  Serverless computing is a good enough solution for improving security, and Docker's lightweight virtualisation were two technologies that filled the market space that I thought Unikernels were going to occupy.  I'd had some experience with Docker and found it to be complex and unwieldy and it seemed likely people would gravitate to the better Unikernel technology once they discovered it.  When serverless hit the scene it was clear this wasn't going away any time soon, and it was also clear that serverless had taken some of the heat out of the application security issue - want a more secure application? Just run it as serverless.  You can't log in to a Unikernel, but you can't log in to a serverless function either. In the time it took me to build bootrino, Docker took over the world.

Unikernels had also been attacked as being "undebuggable" and "unfit for production".  I thought these claims were of no real value and put forward by people who had invested alot in backing the competing container technology.  Nevertheless the criticism seemed to get alot of traction with detractors of the Unikernel concept but it was never a criticism I cared much about - being "undebuggable" was never something that I encountered as a problem.

The flaws with the Unikernel concepts.

While I was building bootrino I discovered some things about Unikernels that were hard to undiscover.

One thing I learned was that sure - Unikernels are extremely minimal, and have no user login system, making them extremely secure, BUT Linux can be built that way too.  Embedded Linux systems such as Yocto Linux https://www.yoctoproject.org allow you to build tiny operating systems that consist only of a kernel plus the application code, occupying only a handful of megabytes.  Hey- that looks alot like a Unikernel!  Purists might object and say they are worlds apart because a Unikernel has a flat address space or some other distinction but I don't care about that stuff.... from a practical perspective - for the factors that I cared about - a stripped back Yocto Linux system is largely the same as a Unikernel.

The next thing I discovered that was hard to ignore was the symmetric multiprocessing story - Unikernels don't have such a story.  They are inherently single core.  That's a big problem in todays multicore world, and whilst there are ways around it by running many parallel single core Unikernels, it became clear to me that in fact the Linux kernel is a really good thing - and lot's of good stuff like handling SMP.  And as a result of my research I discovered also that the Linux kernel can be only a handful of megabytes anyway.  Taking full advantage of multi processors is not something that should be the responsibility of an application - it's a specialised and very tricky thing to get right, and its probably best done by some other bit of software - what should we call that?  Let's call it a kernel.  So what's with the Unikernels obsession with getting rid of the kernel?  There's not alot to be gained from having no kernel, and there is alot to be lost.  Hmmm.

Along the way I discovered you could do all sorts of tricky stuff like building Linux operating systems to run purely from RAM - such as Alpine Linux and TinyCore Linux do.  Again started to become even more blurry to me what the compelling advantage was of a Unikernel over a Run-From-RAM Linux operating system.

And finally the thing that I just couldn't ignore was that Linux let you configure it into very small and secure configurations with full SMP support AND you could run ANY existing Linux languages or applications on those tiny systems.  Unikernels generally seemed to need special builds and toolchains and configuration systems and recompilations to get them to run applications.  This was a huge advantage for Linux in a tiny configuration versus Unikernels.

I spent alot of time getting tiny operating systems to boot on the major cloud computing platforms. One of the times that most influenced my thinking about Unikernels was when I was trying to get MirageOS https://mirage.io - one of the leading Unikernel implementations - working on Amazon, Google and Digital Ocean. MirageOS is interesting in that you can compile the same MirageOS program into either a Unikernel, or into a Linux binary. I got to the point that I had the same MirageOS compiled application running on Amazon, Google and Digital Ocean under Linux, and I also had it running as a Unikernel successfully on Google Compute Engine - it did not work as a Unikernel on Amazon and Digital Ocean.  This was a key moment.  I sat there thinking OK - the very same MirageOS code works well on all three cloud platforms, and works fine Google as a Unikernel, but not the other two.  And I thought "Unikernel or Linux - it's exactly the same practical outcome".  The Linux version was running with nothing more than the MirageOS application binary, a Linux kernel of a handful of megabytes plus a few extra libraries - incredibly minimal.  That moment was a turning point, and it became very hard to see Unikernels as having substantial benefit over Linux at that point. In fact Linux had made it easier and more practical to implement MirageOS due to its better driver support. The only perceptible difference was the MirageOS/Linux implementation was 10 - 15 megabytes larger, which I didn't care about. I wondered then if all this Unikernel effort, and all the associated configuration, programming and loss of SMP, was about trying to save the space taken by 15 megabytes of Linux kernel? Cause the fact is, you can run your system as nothing more than a Linux kernel, plus your application and library code and absolutely nothing more, if you can be bothered configuring it that way.

No doubt unikernel purists will point out that there is a big difference between the definition of a unikernel versus a minimally configured Linux system such as Yocto Linux or Alpine or TinyCore.  Or perhaps they might point out that Unikernels can be only a handful of kilobytes and can boot in milliseconds.  I respect those things but my personal interests never needed those things. I was interested in practical outcomes for my personal use cases and less interested in purist definitions.  

I had come to see that it was possible to build very very small Linux systems, compatible with all Linux software, with all the security advantages of Unikernels, but with the benefit of symmetric multiprocessing and all the Linux driver support and community support.  

In practical terms I'd discovered, and could not undiscover, that for my personal interests and my personal use cases - anything that Unikernels can do, Linux can do better.  What's the real difference between embedded Linux systems and Unikernels?  Not much.  And besides, none of it really mattered anyway because the market wasn't beating a door down for this technology in the way it was flooding toward Docker and serverless. To put it a little brutally but factually - (almost) no one cares about Unikernels because there's no compelling market need.  Technologies that the market really needs get ripped out of your hands and used - to butcher the words of Marc Andressen. Unikernels do not have product/market fit.

And speaking of zero product/market fit - I'm proud of http://www.bootrino.com - the system I built for booting Run-From-RAM operating systems in the cloud, and I have immense respect for the incredible intellect and capability of every person in the Unikernel community - all infinitely smarter and better programmers than me - I was after all just a user of the technology, not one of the heroic individuals building the Unikernel technology - but in the end I just couldn't undiscover that Linux makes a better Unikernel-like OS than Unikernels do. 

The core point of this blog post being that Unikernels have a place in the world, but maybe not for running general purpose applications. Unikernels shine where millisecond boot times count and where you want to squeeze out every single possible instruction and run everything in ring 0.


If you are wanting to run general purpose applications with Unikernel-like minimalism and in Unikernel-like isolation then perhaps consider something like Yocto Linux or Alpine Linux running from RAM or TinyCore Linux in Run-From-RAM mode, and configure out the user login system

I had bet on the horse that wasn't the winner, I'd invested years of work into it, which I don't regret and had alot of fun with.  Off to start the next thing.......

Andrew Stuart
andrew.stuart@supercoders.com.au