In part 1 of this series, we talked about the history of computing and discussed why viewing Platform-as-a-Service (PaaS) as a modern, distributed operating system (OS) may be a good conceptual framework for thinking about its evolution and components.
In part 2, we detail this analogy and conceptual framework by dissecting a classic OS and its most important parts. For each part, we discuss the closest equivalent in a PaaS, using Cloud Foundry as the example. In cases where the analogy doesn’t fit completely, we’ll discuss the differences instead. Additionally, we compare and contrast features of the PaaS offering versus their classical OS components.
First, let’s define a Platform-as-a-Service and its core functions. However, to fully understand a PaaS, we must understand what cloud-native applications are.
A cloud-native application is an piece of software running in a cloud that is designed from the ground-up for cloud environments. Typically, such applications are built by developers who are following the 12-factor methodology or 12 best practices for building cloud applications. Now that we understand cloud-native applications, we can use that definition to refine our PaaS definition.
A PaaS is an operating system for clouds designed to efficiently run cloud-native applications in a scalable manner.
To justify our definition of PaaS, let’s first review important operating systems (OS) concepts and see how these concepts are anchored in Cloud Foundry, an open source Platform-as-a-Service.
Figure 1. Classic OS components architecture overview
Operation System (OS) concepts
The advent of Linux gave the world access to a modern, solid, open source OS that can be used and adapted to various hardware platforms, from the tiny Raspberry Pi to large mainframes. The OS concepts  we discuss below will use Linux as the defacto classic OS, though clearly there are other open source options as well as proprietary operating systems. We chose this open source operating system because the concepts and features in Linux are also often adopted in proprietary OS, so you should be able to follow along with those concepts, whether you use Linux, another open source OS, or a proprietary OS like Apple Mac OS or Microsoft Windows.
Every OS, whether running on real or on virtualized hardware, needs a boot-loading mechanism. This is done via a bootloader (firmware) that is typically burned into the hardware system. For virtualized hardware, this bootloader might just be a small independent piece of code that can run on a host OS to load the other one.
Figure 2. OS bootloader vs CF BOSH
Cloud Foundry also has a bootloader named BOSH. However, unlike a classic OS loader, BOSH is a tool that loads and manages a distributed deployment of Cloud Foundry into a concrete Infrastructure-as-a-Service (IaaS). Unlike other bootloaders, BOSH also includes facilities that Cloud Foundry operators can use to keep it up-to-date and functioning in case parts of the environment have failed, for example, when a VM crashes.
Additionally, unlike a typical OS bootloader, BOSH also provides a hardware abstraction layer (HAL) which is found in classic operating systems that need to run on different hardware platforms. For BOSH, this HAL is most concretely represented by the BOSH CPI (cloud provider interface) which abstracts BOSH from the targeted IaaS. Using this CPI decoupling approach, you can deploy and manage Cloud Foundry on a variety of IaaS, including AWS, Azure, OpenStack, Google Cloud Platform, vSphere, SoftLayer, and many others.
Every OS has a kernel, which is essentially the core component in the OS that starts the main execution loop, dispatches all user or I/O requests, and starts associated processes. As the name indicates, it’s the heart (or kernel) of the system. For a classic OS, the kernel’s other responsibilities may also include managing users and access control. Essentially, the kernel does bookkeeping for the system’s resources and its users. Technically, sometimes this bookkeeping is done using a file system, which can be seen as a different component. However, for practical purposes, we can view the file system as an extension to the kernel.
Figure 3. Kernel of classic OS
In a cloud operating system such as Cloud Foundry, a similar central component exists, but it’s called the Cloud Controller API (CAPI). The CAPI subsystem is responsible for managing all access to Cloud Foundry, as well as doing necessary bookkeeping.
Additionally, typical OS kernels often have the responsibility of scheduling tasks and resources, as well as ensuring process execution isolation and fairness. Below, I talk about these responsibilities separately, since other components typically implement them (either attached to the kernel or being part of it).
Since computing resources are usually scarce, any OS needs to have a scheduler that prescribes a schedule (which one and what order) of the execution of processes (or jobs) onto the limited resources that also have limited availability. While the execution is constant and jobs might take a long time to terminate (or never terminate, like for server jobs), the scheduler needs to be able to preempt processes to allow execution of other processes. This allows the scheduler to be fair.
In Cloud Foundry, the most comparable component to a typical OS scheduler is the Diego subsystem, which prepares, schedules, and runs applications. Diego is designed to be a fix scheduler for long running processes (LRPs) which are, in essence, containers running the pushed applications with an associated environment (part of the Buildpack).
The containers are run in cells (VMs) which have limited CPU, memory, and hard disk space. So, part of the Diego scheduling is finding the correct cell with enough resource for the container in question. The Diego scheduler uses a distributed auction algorithm to make that decision. Additionally, when containers crash (due to an application crashing or otherwise), the Diego subsystem is also responsible for identifying the crash and restarting the application, which might then move to a new cell. This healing feature of Diego is not typically part of the schedulers of classic OS.
In operating system design, especially for multiuser operating systems, the concept of process isolation is an important feature. The primary problem is how to isolate one processes data from accidental (or intentional) access by another (non-child process). Besides the obvious security reason, isolation allows for stable operation and sharing of the machines’ resources.
Figure 4. Isolation in PaaS
Modern OS such as Linux, Windows, and MacOS X do a great job of isolating process execution. However, their primary recourse is to use the hardware’s primitives to isolate each process’ memory and execution stack. The Intel architecture, for instance, allows the hardware to distinguish between privileged and unprivileged users and process execution. A user process is not automatically granted any privileged access; it can only access memory allocated to it by the kernel’s memory manager. By taking advantage of these hardware primitives, modern OS were able to create robust process isolation.
How can this process isolation be achieved in a cloud OS–especially when everything is virtualized (hardware and even the OS itself)? The primitives guaranteed by the virtualized hardware are no longer automatically applicable at the container-level. Furthermore, since a user could potentially have apps running in different containers spread across many VMs, the “user” is no longer a good enough high-level concept for isolation identity. A collection of apps—a space in Cloud Foundry—is more appropriate. Complicating matters is the fact that VMs and containers are often re-created and don’t usually execute in the same data center they initially executed on—so definitely not the same physical hardware.
Isolation segments allow us to address these important constraints and provide the isolation guaranteed in Cloud Foundry. These isolation segments are a way for a collection of apps to execute in the same hosted physical hardware and hypervisor. Using isolation segments gives users a level of security and assurance that their applications are not sharing resources with neighboring applications that they have no control over. However, unlike in a classic OS where isolation is guaranteed by hardware, in Cloud Foundry, the isolation is done essentially by tagging VMs and indicating to CAPI the placement of an application. The Diego scheduler will then attempt to run the application only in VMs with matching tags.
Input and Output (I/O)
Every OS uses some form of input and output (I/O) to communicate outside the OS (peripherals and network devices) and to allow peripherals and network devices to communicate with the OS. Therefore, an I/O subsystem is crucial to a classic operating system. I/O constitutes not only the most extensible component of the system, but also the most useful component since it allows differentiation and specialization.
For a cloud operating system, the I/O subsystem is also the one with the most extensions and potential for differentiation. In Cloud Foundry, the most obvious place where I/O is done is via the service broker interface which allows for a marketplace of external third-party services to be added and used by CF applications.
Figure 5. Input and Output in classic OS vs Cloud Foundry PaaS
The CF service broker marketplace is open and recently has become its own standard (openservicebrokerapi.org) that other PaaS are adopting in their architecture. For Cloud Foundry, the service broker and associated services have contributed to helping create not only an active marketplace for services but also a way for different vendors of Cloud Foundry to differentiate their offerings.
Since operating systems are designed to run applications for users, they typically specify the format that these applications must adhere to. Remember that an application includes static and sometimes dynamic dependencies that must be loaded and linked in order to run. OS have specific application formats and specify the details on how libraries can be packaged and loaded.
It’s no surprise that Cloud Foundry also has a similar set of requirements for the applications that it runs. The format for a Cloud Foundry application is specified as the packaged app that $cf push command creates and the dependencies are the buildpacks that the application uses. The Cloud Foundry buildpack extension point is flexible and allows for almost any kind of server-side application to be executed in Cloud Foundry.
An important part of any OS is the user interface it exposes for end users. Classic OS typically have command line interfaces, as well as elaborate graphical user interfaces (GUI) that simplify the interactions of end users with the OS. The amount of innovation in GUIs in the 1990s and 2000s resulted in personal computing operating systems that are ubiquitous to most people who use computers.
For a cloud OS such as Cloud Foundry, the primary user interface is via the command line interface (CLI) which constitute not only the interface for end users but also for administrators of a Cloud Foundry environment. There are no built-in GUIs for Cloud Foundry. Instead, different vendors differentiate their offerings with some web-based GUI that constitute a console for their Cloud Foundry environment (See Bluemix example and Pivotal Web Services example). The primary goal of a console to Cloud Foundry is similar to a classic OS GUI—it’s to help simplify usage.
As you can see, there is an almost one-to-one mapping between key classic OS high-level concepts to some equivalent in Cloud Foundry. Sometimes, the mapping is not perfect and the importance of the component in a classic OS does not translate in Cloud Foundry, and vice versa. However, many of the concepts do map well.
Using the conceptual framework of an operating system and using the history of OS evolution and innovation, we will attempt to lay some groundwork on where we believe Cloud Foundry—and PaaS in general—will evolve or where innovation may be ripe.