That's an external controller, which is what most people are doing themselves these days, reinventing the wheel each time. Borg has long had an automatic rollback feature on updates, tuned through a few settings on top of the health check machinery. I'm in the camp believing that a basic implementation should be built-in, since health checks are already there. An implementation of this was started, but it has stalled. External controllers should be still allowed, for more advanced scenarios like rolling back upon detection of regressions in latency and similar.
Also, setting up Spinnaker is pretty much as complicated as Kubernetes itself. :-)
How does Borg express updates? With Kubernetes only deployments have rollout/rollback, and you need something like Helm -- which is frankly not that great -- to handle groups of resources that are to be updated and versioned together, e.g. configmaps and services.
AFAIR, you can only update jobs (collections of single containers) and allocs (pods inside of which jobs will schedule and run: you need to state that job J lives inside alloc A, otherwise it will run in an anonymous, implied alloc). There aren't other objects you can manipulate, actually.
Configmaps don't really exist, although something similar is achieved with a job that has a second package holding just the data. This is why I think multi-image containers should be implemented, but also a reason why they haven't been yet: configmaps cover some use cases. When a job replica (task) gets updated or rolled back, both packages change in sync. On Kubernetes, you'd use version numbers in the configmap name (but you need to worry about garbage collecting unused ones).
Services live outside of Borg entirely. GSLB has its own push mechanisms and only consumes Borg's lists of containers that comprise a given Borg job.
From the paper:
> A user can change the properties of some or all of the
tasks in a running job by pushing a new job configuration
to Borg, and then instructing Borg to update the tasks to
the new specification. This acts as a lightweight, non-atomic
transaction that can easily be undone until it is closed (com-
mitted). Updates are generally done in a rolling fashion, and
a limit can be imposed on the number of task disruptions
(reschedules or preemptions) an update causes; any changes
that would cause more disruptions are skipped.
Some task updates (e.g., pushing a new binary) will al-
ways require the task to be restarted; some (e.g., increasing
resource requirements or changing constraints) might make
the task no longer fit on the machine, and cause it to be
stopped and rescheduled; and some (e.g., changing priority)
can always be done without restarting or moving the task.
Also, setting up Spinnaker is pretty much as complicated as Kubernetes itself. :-)