Yo Dawg, I Herd You Like Servers, So We Put a Server in Yo Server so You can Serve More Servers
Like an Xzibit Meme, server virtualization is full of recursion. Let’s look at the components and see how.
First, there’s the virtual machine “host”. The host is usually a physical computer — although it can also be virtualized — that runs something called a “hypervisor”. A hypervisor is a software component that manages virtual machines.
Then there are virtual machine “guests”. These are the virtual machines that run inside the host.
The following image from RedHat depicts this structure:
Ape Shall Never Kill Ape
With this structure in mind, let’s look at a typical Infrastructure-as-a-Service layout:
Here, we have three compute nodes that are hosting a total of 18 virtual machines belonging to three different projects.
Not all virtual machines are created equally. Some might have 4 CPUs and 8 gigabytes of RAM, while others might only have 2 CPUs and 1 gigabyte of RAM. The hypervisor running on each compute node (another term for a virtual machine host) manages this CPU and memory allocation, as well as the starting and stopping of each virtual machine on the node.
While all modern hypervisors can handle these basic functions, there are several other functions that a modern virtual machine host should provide. These include ensuring that the actions of one virtual machine do not adversely affect the actions of another.
Let’s say Project Purple begins an IO-intensive job on Compute Node 1. Project Green, also on Compute Node 1, will incur a performance hit and there’s nothing he can do about it. This is similar to when you’re filling your car with gas and halfway though someone pulls up and begins using the same pump. The flow of your gas noticeably slows down.
Along with IO throughput, other unchecked resources include (but are not limited to) CPU cycles and frequency, and network throughput and bandwidth.
Obviously, this is not the type of service one would want to provide to users — especially in a public cloud environment. A better solution would be to segregate all projects so their usage does not affect other projects.
In Linux, this type of control is implemented using Control Groups (cgroups). Googling for “cgroups” provides a wide array of introductory articles on the subject (this Oracle article is a great in-depth intro), but I haven’t been able to find a mature system built on top of cgroups to easily partition and manage arbitrary groups of users. This feature was suggested for OpenStack, but now looks to be abandoned. But in my opinion, it’s only a matter of time before it gets noticed again.
While cgroups can effectively manage resource control between groups, there are other systems that can further support management and partitioning, such as namespaces and advanced IPTables. While OpenStack may not be utilizing cgroups, OpenStack Quantum uses Linux network namespaces to support overlapping IP addresses.
Isn’t This Where We Came In?
Once all of these systems are in place, you can begin to see how the Virtual Machine Host will not just host virtual machines, but also coordinate resource allocation and usage between the virtual machines. In this way, the Linux operating system installed on the host becomes more of a meta operating system whose sole purpose is to manage other operating systems.
The end result is a monolithic server, capable of efficiently managing distinct allocations of computing resources that are properly partitioned from one another. This is starting to sound a little familiar…