A dark factory is a control loop. Kubernetes is the most boring control loop in production. That is the reason.

What the substrate has to do

A dark factory has four requirements from whatever it runs on.

  1. Declarative desired state. The system has to be able to say "I want N copies of this artifact running, signed, behind this policy," and have the substrate reconcile to that state unattended.
  2. Restart and replace as a primitive. Failures are the steady state. "Kill it and start a new one" has to be cheap, automatic, and observable.
  3. An operator-extensible control plane. The factory grows new resource types as the system grows. The substrate has to treat those types as first-class, not as jobs squashed into the lowest common denominator.
  4. Boring upgrades. The factory runs unattended. The substrate cannot require a person to read release notes on a Saturday.

Kubernetes is not special because it is fast, or because it scales, or because it is cloud-native. Kubernetes is special because it is the only widely-deployed substrate that makes all four of those requirements boring.

Why the alternatives fall short

Serverless (Lambda, Cloud Functions, Workers) gets close on restart-and-replace. It fails on declarative desired state. The platform owns the loop, not you. The moment you need a custom resource type, the platform tells you no. A factory that wants to define a BuildRun cannot do it on Lambda.

Systemd on a VM gets close on boring upgrades. It fails on the operator-extensible control plane. The minute you want a custom resource type, you are writing your own reconciler. You are now maintaining a control plane in addition to the factory. The single engineer does not have that time.

Nomad is the most underrated of the three. Nomad is what Kubernetes would look like if HashiCorp had cared more about operator patterns and less about service mesh. Nomad is excellent. Nomad is also a single-vendor system, and the ecosystem of pre-built operators and CRDs does not exist. You will build everything from scratch.

Docker Compose on a single host works until the host dies. Then the dark factory is dark in a different sense. The lights are off. The artifact is gone. You find out what your backup posture actually is.

The single-engineer argument

An operator is a reconciler. The operator watches a custom resource. The operator makes the cluster match the resource. The operator is written in Go and packaged as a container. The operator runs the same way the artifact runs. The operator is part of the factory.

A platform team cannot build a custom resource type faster than a single engineer with an operator template. The single engineer's bottleneck is the spec, not the infrastructure. The infrastructure is the easy part. The hard part is figuring out what the factory should do, and that is the same problem at any team size.

What Kubernetes does not give you

Kubernetes does not give you a factory. Kubernetes gives you a substrate on which a factory can be built. The gap between "I have a cluster" and "I have a factory" is where the operator pattern lives.

Kubernetes also does not give you provenance. The cluster will run whatever artifact you give it. The cluster does not know where the artifact came from. The cluster does not know whether the artifact was generated from a spec, or by a human, or by a model with no spec. The cluster does not care. Provenance is a layer above the substrate, and that is where the dark factory actually lives.

If you are a single engineer trying to build a dark factory, the choice of substrate is not really a choice. Kubernetes is the answer. The interesting work is what you build on top of it.