Desired-state contracts
This is the idea the whole product is built around, so it is worth understanding precisely rather than by analogy alone.
Desired vs actual, and who owns which
- The centre holds desired state. It is declarative — you describe the end state you want (a vSwitch with these adapters, a vNIC with this VLAN), never a sequence of steps. The centre never imperatively drives a host.
- The agent on each host continuously compares actual state (what the host is really configured as, read live) against desired state (what it was last told to enforce), and emits idempotent operations to close any gap.
- The agent also keeps a last-honoured copy of its desired state in a local embedded store. If the centre becomes unreachable, the agent does not stop or fall back to some default — it keeps enforcing exactly what it was last given, and reports itself as running autonomously.
This is what makes Ballast different from a centralised-only model: losing the centre never changes intent on a host, only the ability to change that intent.
Generation and ObservedGeneration
Every desired-state object carries a Generation, incremented by the
centre each time it changes. The agent reports back
Status.ObservedGeneration — the generation it has actually reconciled
actual state to.
Generation == ObservedGeneration— settled; the host matches what was asked of it.Generation > ObservedGeneration— a change is outstanding; the host has not yet caught up, whether because it is mid-reconcile or because it is offline from the centre and reconciling against an older cached copy.
The console's drift indicator is built directly from this pair, not from a generic health check.
Drift detection
Drift is any difference between what the agent finds on the host and what its current desired state says should be there — someone changing a vSwitch by hand in Hyper-V Manager, for instance. The agent detects this on every reconcile pass.
Auto-revert vs approval-gated
Not all drift should be corrected the same way, and how each Spec field
should be handled here — which are auto-reverted immediately and which
require an operator's approval before the agent is allowed to act on them — is
TBC. This page will describe the actual policy, and where in the console it
is configured, once decided and shipped.
Idempotency, non-negotiably
Applying the same desired state twice must always be a no-op. Every reconciler is written and tested to this rule; it is what makes the reconcile loop safe to run continuously rather than only on a triggered change.