I’m completely ignorant about this and likely just missing the point but: isn’t the point of an OS to not have to (vibe)code filesystems and networking by hand every time you need them? Also, how does a unikernel cooperate with other applications? Would they all live in separate networked unikernels managed by a hypervisor? And, if they all (vibe)coded their own fs and network wouldn’t that introduce subtle bugs and inconsistencies that would eventually bring the whole thing down and lead you back to the need for shared primitives in the first place?
Maybe a good halfway point is to still have a unikernel but the libraries for common stuff like networking or fs are already written according to a standard and plug and play and reusable across applications?
Unikernels simply redraw abstraction boundaries. You can still use libraries and third-party code to implement common primitives. In fact, that's exactly what many unikernel frameworks give you (unikraft, hermit, mirage)
I guess the others have made these points, but since unikernels run in VMs with virtual hardware, I guess a virtual ethernet card can have an interface that's easy to program for, making the driver trivial. You're not talking to real hardware in any case.
Similarly, a filesystem's just a data structure that happens to be on disc. You can mmap your harddrive and let the host hypervisor handle swap, preemption etc.
It's similar to a process contract, but with slightly different boundaries
The thing I don't get: We'll now run those N unikernel things in VMs with a hypervisor underneath. How is that different from running static binaries in a locked-down OS, i.e., with a traditional kernel? You can surely break out of a unikernel by "popping the kvm" as the article mentions. How is that more secure? In principle we are running the same things, just call them differently (app becomes unikernel+app, kernel becomes hypervisor).
It is not any different. Actually, it is worse because a VM is a much worse environment to run a application since you need that unikernel stub as well as the application.
The only advantage is that cloud services provide VM tenants so you are already stuck with a VM substrate and you want to minimize layers from that point on.
However, as a practical matter, the design of the Linux kernel is grossly insecure and basically impossible to make even remotely safe as evidenced by the unending sprawl of LPEs. Hypervisors are generally designed and configured in a way that is only reasonably insecure.
However, there is nothing stopping you from designing a kernel in a similar way and providing shared tenant processes with similar guarantees. You just need to port your applications to the new operating system, but you would need to port them to a unikernel anyways if you wanted to go that route.
The only free action is lumping your applications with the full OS and dumping it onto a hypervisor. Anything else has porting work which is why the multi-tenant VM model is advantageous at all in the first place.
Both have weaknesses, but with an OS, you have certain bottlenecks - like your app memory is paged and has its own memory space, data structures are often duplicated in user and kernel memory, syscalls have cost, which is why io_uring is a thing in Linux.
This is all unnecessary overhead and complexity, as the OS doesn't really mediate hardware access in this case.
But you're right on some points, it's not really more secure, but there's a hell of a lot less complexity where things can go wrong.
It's conceptually equivalent but the details differ. The program has access to more abilities and in terms of common conventions the security boundary is much more robust. If nothing else I'd argue it's a superior abstraction with which to make the delineation.
You don't build the networking or filesystem by hand every time you need them. You pull them from reviewed and maintained library code from a repository. That's how MirageOS etc work. Someone else has written e.g. TCP/IP -- hopefully well -- and you link against it.
The point that makes this different from an OS is that there's no shared service, no syscalls to do that stuff -- just subroutine calls -- and no timesharing (except at the hypervisor level). It's just a single runtime running on hypervisor direct against the virtualized hardware.
Because, yeah, all this work has happened in hardware in the last 30 years to make that possible, but we still treat the operating system as the best unit of resource sharing. When in fact it's kind of a jack of all trades master of none. If you're booting a whole linux kernel -- with its giant framework built to co-tenant a pile of applications and users -- just to run one process, there's definitely something to look at there. Even if the unikernel space itself is relatively immature.
You don't need to emphasize the "vibe coded every time you need them" thing. That's not what anybody was being talked about in the article. The "vibe coding" piece is pointing out that the missing pieces in the ecosystem can be more rapidly filled in now because of agentic tooling.
> running on hypervisor direct against the virtualized hardware.
Well, here is your actual OS then. You named it "hypervisor", and changed the system interface, but it's still there, revirtualizing the access to hardware and ensuring separation of different users/applications/unikernels.
Yep. Except every application runs in a down-and-dirty virtual machine instead of a nice clean process, so they get to experience the joy that is hardware booting and get to configure virtual device buffers instead of calling send(). Progress.
This isn't too dissimilar to DOS programs. DOS also gave you a filesystem, memory management, a shell a process loder, driver interface, but it was all in real mode, and you were free to replace these components with your own as you pleased.
Or if you're more familiar with embedded, like a BSP or RTOS
Arbitrating access to the hardware between multiple tenants still gonna be a PITA (as it was during the DOS days), especially if you want to expose actual hardware, not some generic VirtIO devices. Even with the latter, the hypervisor would have to do quite a bit of the resource management and interface translation.
Unless you're literally running a single application on a dedicated piece of hardware in which case... yeah, sure, you can do the OS-as-a-library schtick. But you could do it 10 years ago, too.
I mean, sure we can put labels wherever we want. I don't really care. MirageOS even has "OS" in its name.
The point is all the other things: total number of lines of code, permissions and security, memory management, drivers, process mgmt, it all changes.
Does it though? And I'd really like to see how you'll revirtualize e.g. an NVIDIA GPU (notoriously context-full piece of hardware), while allowing transparent shared access to it from different applications. Heck, you'll run into trouble with most of PCI-connected devices except for the most primitive once.
yea, "virtualizing" an NVIDIA GPU is not truly feasible right now from what I see.
I do know that AMD has done more in this space. When I worked at Google there were (other) people on the Stadia team doing this. And some open source bits out there that I've seen, including from AMD.
Unfortunately, my real world work... and most real inference etc work others are doing... is on CUDA/NVIDIA.
Over time, what prevents the reviewed-and-maintained-library-code from developing creeping featuritis and consequently evolving the additional attack surface that unikernels currently lack?