What Is Vsock and Why Use It with Unikernels?
nanovms.com
nanovms.com
Later on certain people started to see that these high-level concepts are bad. Operating systems are insecure. Context switching has overhead. Page table handling is expensive. So unikernels are invented.
People later discover that unikernels are somewhat hard to work with, as the only way they can talk to the outside world is through virtio-like devices:
- Unikernels aren't capable of just writing something to a simple file. No, they must write to a raw block device. Hey, that's annoying. Let's bring back support for native file access using virtio-fs! https://www.qemu.org/2020/11/04/osv-virtio-fs/
- Unikernels are also not capable of simply streaming data to another application. No, they must include their own Ethernet/IP/TCP stack, and on the host system you must set up a network bridge (hopefully with a firewall) just to let a couple of unikernels talk to each other. So let's solve that using AF_VSOCK!
At what point do unikernels become indistinguishable from ordinary processes running on top of an OS kernel in terms of features/behaviour, but reinvented poorly? I have the feeling that we're coming full circle at this point.
Compared to other unikernels designs where the OS layer is minimal but mostly fixed.
[1] https://www.linux.com/wp-content/uploads/2021/02/unikraft1.p...
Unikernels ask the very pointed question - if we're already being deployed as virtual machines and using these abstractions why not get rid of everything else and pick up the security, performance, etc.
People see that the operating system is insecure, so they run the operating system as a virtual machine on top of a hypervisor. The hypervisor operates the system as a bundle of virtual machines and provides shared services to them. People realize the hypervisor is just a operating system, so they target the hypervisor API instead of the kernel API and thus unikernels are invented.
The question then becomes: Why unikernel on a hypervisor instead of a process on a operating system?
The standard answer is that hypervisors are more "secure". However, this is total nonsense. Any technique that made a hypervisor "secure" could be directly applied back to a normal operating system as they are solving the same fundamental problem of multiplexing a single machine to run multiple programs.
To quote Theo de Raadt: "You are absolutely deluded, if not stupid, if you think that a worldwide collection of software engineers who can't write operating systems or applications without security holes, can then turn around and suddenly write virtualization layers without security holes."
The actual answer is that everybody sucks at multiplexing hardware, so everybody knows the old stuff does not work. However, they do not know the new stuff does not work yet, so they bet it all on the new stuff. Unikernels on a hypervisor are a strictly inferior solution to a process on a operating system, but people think hypervisors are better than operating systems, so they develop unikernels. The truth of the matter is that you just need a better operating system so you can develop processes which is a strictly better model.
What next, perhaps, a VMM for VMMs? a VMMM?
Linux has so many system calls, and with each new one you get a whole new attack surface (e.g. most recently with io_uring).
But the attack surface with hypervisors is pretty static, and perhaps can be better reasoned about.
Again, not strongly arguing which is safer, but just pointing out that there is a pretty fundamental difference between the two that could make for a difference in security.
Processes and OS services are a strictly better model than virtual machines and virtual devices when developing a program. They fulfill the same purposes, but the operating system model is less clunky as you are "virtualizing" a ideal machine that requires no setup and ideal devices that requires no setup. In contrast, virtual machines and virtual devices expose a API that includes the nitty-gritty details of actual hardware which is just a distraction when developing a regular old application.
You actually see a funny convergence where optimized hypervisors implement specialized virtual devices that do not exist in reality that offer streamlined interfaces. These are basically the reinvention of operating system interfaces as the virtual machine guests (processes) consume a abstract interface that the hypervisor (operating system) maps onto the actual hardware. They also support specialized virtual devices for communicating between guests (IPC calls). Reinvention for everyone, but worse, yay.
Unfortunately, nobody wants to do this because everybody wrongly believes that hypervisors are magically more secure than operating systems for the reasons I stated in my previous comment. This is really the only thing propping up the hypervisor and, by extension, the unikernel concept. As soon as you no longer believe they are magically more secure there are hardly any reasons to prefer a hypervisor over a properly designed operating system beyond the one use case I mentioned in a sibling comment which is running a binary-only program targeting a different operating system.
Here's what it could look like if it were solved at the operating system level. This is a talk about the Helios microkernel, which is based on seL4. https://drewdevault.com/2023/02/20/2023-02-20-Helios-aarch64...
The most important thing he says in the whole talk is that "Helios can run another instance of itself within itself, without virtualization".
We don't need any of this extra complexity, emulating entire machines, to be secure. We just need to build applications on top of APIs which allow for security. An application that needs a few seL4 endpoints to do its job is much easier to properly integrate into a secure system, than an application which expects the whole POSIX circus.
The authors behind the paper observed that people were deploying single purpose VMs on top of hypervisors. Those VMs included full-blown general purpose OSes. Many of the features provided by those OSes were unnecessary for this use case. That bloat not only lead to large image sizes, but also worse security caused by increased attack surface.
As a solution, the authors proposed a new class of OS which they named unikernels. Simply put, they're library OSes targeting hypervisors. By using a library OS, the compiler would ensure that only features that are necessary would be included in the application image. And by targeting the hypervisor, the OS would be able to rely on high level primitives provided by hypervisors such as multitasking, isolation, and device handling.
So taking this into account, let's go through your claims:
> Later on certain people started to see that these high-level concepts are bad. ... So unikernels are invented.
This isn't what unikernels are about. Nothing about the concept precludes implementing high level primitives in the OS. They just drop features that aren't required for the application on an individual basis. It's not about throwing every Unix features out of the window.
> Unikernels aren't capable of just writing something to a simple file. No, they must write to a raw block device.
That's not a description of unikernels. That's a description of the hypervisor's interface with guest OSes. Traditional OSes would have to deal with block devices too. Nothing about unikernels prevents them from implementing file system drivers like a traditional Unix system would.
> Unikernels are also not capable of simply streaming data to another application. No, they must include their own Ethernet/IP/TCP stack, and on the host system you must set up a network bridge (hopefully with a firewall) just to let a couple of unikernels talk to each other. So let's solve that using AF_VSOCK!
Again, you're describing hypervisors. Unikernels can implement communication mechanisms as they see fit. Unix OSes very much need to implement their own IPC and networking stack too, if they want their applications to be able to communicate. The difference is that unikernels only have to deal with virtual devices, a much narrower target than general purpose OSes. That can lead to efficiency and security benefits.
> I have the feeling that we're coming full circle at this point.
We didn't.
Unikernels can boot incredibly fast. Compared to a normal virtual machine that can take seconds to boot unikernels can boot in 50ms (quote from a white paper on the nanovms website)
Considering that unikernels, by definition, don't have any userland, you really need to compare the unikernel boot time to the "time to reach init" boot time on a traditional OS -- which is under 100 ms with a Linux kernel, and down to 20 ms with FreeBSD now. A unikernel boot time of 50 ms really isn't anything special.
I think as you point out where wasm can shine are the function-as-a-service platforms, although the memory safety issues would probably need to be addressed at some point (writing to 0x0, no ro mem, etc.).
I'll also say that if you are setting up your own bridge and using something like dhcp nanos actually boots faster than the response can come in sometimes so there' s a flag you have to set. I think the 'fast boot time' usecases are a relatively small set.
Having said that there are many many other performance considerations besides fast boot time such as throughput, or request/second or random io read/writes/etc.
Many web languages are single-process/single thread (eg: all interpreted ones) and since that is the vast majority of our users it isn't a problem. Threads are great if you have access to them and if not you scale horizontally (just like the interpreters do today). Multiple processes as an architectural design outside of scaling (and numerous issues when it actually does come to scaling) is something the industry really needs to reckon with.
* security - nanos supports much of the same security you'll see on linux but provides more: aslr, no stack/heap exec, rodata no exec, text no write, no null mapping; virtio-rng (for some clouds where it is supported - not everywhere it is), pledge, unveil, honestly - there's a lot here
* monitoring - plenty of apm vendors work out of the box but also things like cloudwatch, and our own custom service as well
* performance measurement - we have things like ftrace and many other tools
* backup - pretty easy to clone vms
* auditing - glad you pointed this out as this becomes much much easier; we actually analyzed a bunch of STIGs and measured the reduction for each STIG as compared to nanos - scroll down to the page here: https://nanovms.com/security - essentially if you are in a regulated industry like finance, health or defense this is a major benefit
* fs ACLs - we have unveil support and many other nanos specific things
Progress on speeding up the FreeBSD boot over the years:
FreeBSD 11.1-RELEASE on EC2: 28208 ms. FreeBSD 13.1-RELEASE on EC2: 9698 ms. FreeBSD 14.0-CURRENT on Firecracker: 620 ms.