A Short History of Deployment Processes

Learn about the history of deployment processes.

The beginning

In the beginning, there were no package managers, because there were no other package formats (like JAR, WAR, RPM, and DEB). Package managers maintain a database of software dependencies and version information to prevent software mismatches and missing prerequisites. The best we could do at that time was to zip files that formed a release by manually copying files from one place to another. When this practice was combined with bare-metal servers, which were intended to last forever, the result was disastrous. After some time, no one knew what had been installed on the servers. Constant overwrites, reconfigurations, package installations, and mutable types of actions resulted in unstable, unreliable, and undocumented software running on top of countless OS patches.

Configuration management tools

The emergence of configuration management tools (e.g., CFEngine, Chef, and Puppet) helped to decrease the mess. They improved OS setups and maintenance more than deployments of new releases. They were never designed to do that, even though the companies behind them quickly realized that it would be financially beneficial to extend their scope.

Even with configuration management tools, the problems with having multiple services running on the same server persisted. Different services might have different needs, and sometimes those needs clashed. One might need JDK6 and the other JDK7. A new release of the first one might require JDK to be upgraded to a new version, but that might affect some other services on the same server. Conflicts and operational complexity were so common that many companies would choose to standardize. As we discussed, standardization (with clear isolation) is an innovation killer. The more we standardize, the less room there is for coming up with better solutions. Even if that’s not a problem, standardization with clear isolation means that it is very complicated to upgrade something. Effects could be unforeseen and the sheer work involved in upgrading everything at once is so significant that many choose not to upgrade for a long time, if ever.

Press + to interact

The need of the hour

We needed process isolation that would not require a separate VM for each service. At the same time, we had to come up with an immutable way to deploy software. Mutability was distracting us from our goal of having reliable environments. With the emergence of virtual machines, immutability became feasible. Instead of deploying releases by doing updates at runtime, we could now create new VMs with OS updates, patches, and our own software baked in. Each time we wanted to release something, we could create a new image and instantiate as many VMs as needed. We could do immutable rolling updates! Still, not many of us did that. It was too expensive in terms of resources and time, and having a separate VM for each service resulted in too much unused CPU and memory.

Docker and containers

Fortunately, Linux had namespaces, cgroups, and other things that were all known as containers. They were lightweight, fast, and cheap. They provided process isolation and quite a few other benefits. Unfortunately, they were not easy to use. Even though they had been around for a while, only a handful of companies had the know-how required for their beneficial utilization. We had to wait for Docker to emerge to make containers easy to use and accessible to all.

Press + to interact

Today, containers are the preferred way to package and deploy services. They are the answer to immutability we were so desperately trying to implement. They provide the necessary isolation of processes, optimized resource utilization, and quite a few other benefits. And yet, we still need much more.

Why container schedulers?

It’s not enough to run containers. We should be able to scale them, make them fault-tolerant, provide transparent communication across a cluster, and many other things. Containers are only a low-level piece of the puzzle. The real benefits are obtained with tools that sit on top of containers. Today, those tools are known as container schedulers. They are our interface. We do not manage containers; they do.

In case you’re not already using one of the container schedulers, you might be wondering what they are.