Container Orchestration in 2014: Taming the Docker Explosion on KVM
It is December 2014. Docker 1.3 is out, and it has fundamentally shifted how we think about deployment. The days of fighting dependency hell on a shared server are ending. But we have traded one problem for another: Orchestration.
Running one container is easy. Running fifty containers across a cluster of servers? That is where the headaches start. I have spent the last three weeks migrating a high-traffic Magento backend from a monolithic bare-metal setup to a microservices architecture. The promise was agility; the reality has been a maze of networking scripts and manual restarts.
If you are trying to run Docker in production today, you are likely looking at three main paths: the developer-friendly Fig, the distributed CoreOS Fleet, or the battle-tested Configuration Management approach. Let's break down what actually works for a Norwegian business prioritizing uptime and data sovereignty.
The Hardware Reality: Why OpenVZ Won't Cut It
Before we touch software, we must address the infrastructure. Docker relies heavily on Linux kernel features like cgroups and namespaces. Most legacy VPS providers in Norway are still stuffing customers onto OpenVZ containers running ancient 2.6.32 kernels.
This does not work for Docker. You will hit kernel panics, loopback mounting errors, and inexplicable networking failures.
To run Docker reliably, you need a full Kernel-based Virtual Machine (KVM) where you control the kernel. We deploy on CoolVDS because they provide KVM virtualization by default, allowing us to run the latest 3.10+ kernels required by Docker 1.3 without begging support for a kernel module update.
Option 1: Fig (The Developer's Choice)
Fig has taken the dev world by storm. It allows you to define your container environment in a simple YAML file. It is excellent for local development on your laptop.
web:
build: .
command: python app.py
ports:
- "5000:5000"
volumes:
- .:/code
links:
- redis
redis:
image: redis
However, Fig (currently) is not an orchestration tool for multiple hosts. It assumes a single Docker socket. If you try to push this to production on a single node, it works, but it lacks the resilience and monitoring required for a business-critical application. It is a stepping stone, not a destination.
Option 2: CoreOS & Fleet (The Bleeding Edge)
For those willing to bleed a little, CoreOS is the most exciting development in 2014. It is a minimal OS designed specifically for massive server deployments. It uses fleet, a distributed init system that treats your entire cluster as if it were a single init system.
Instead of SSHing into a specific server, you submit a Systemd unit file to the cluster, and Fleet decides where to run it. Here is what a high-availability Nginx service looks like in a Fleet unit file:
[Unit]
Description=Nginx Service
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill nginx-main
ExecStartPre=-/usr/bin/docker rm nginx-main
ExecStartPre=/usr/bin/docker pull nginx
ExecStart=/usr/bin/docker run --name nginx-main -p 80:80 nginx
ExecStop=/usr/bin/docker stop nginx-main
[X-Fleet]
Global=true
The Global=true flag is powerful—it ensures an instance of Nginx runs on every machine in your cluster. If a node dies, Fleet handles the state.
The Trade-off: CoreOS is complex. Debugging distributed etcd clusters when the network latencies spike is not for the faint of heart. You need extremely low latency between nodes. In our testing, the CoolVDS network within Oslo (connecting to NIX) provided the sub-millisecond ping times required for stable etcd consensus.
Option 3: The Pragmatic Ansible Approach
For the