Documentation
¶
Overview ¶
Package reconcile holds the diff and converge logic at the heart of the agent. It compares the desired state (from the control plane) against the actual state (containers on the host carrying our label prefix) and converges: start missing, stop extra, restart unhealthy or stale. Every operation is idempotent and safely retryable, so a converge that is interrupted and re-run reaches the same end state.
The logic here depends only on the docker.Client interface, so it is fully unit testable with a fake client (see reconcile_test.go).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Apply ¶
Apply executes a plan against the docker client. It is idempotent: a step whose effect is already in place is a cheap no-op, and a failure on one step does not abort the rest, so the next poll retries what did not land. The set of errors encountered is returned joined, so the caller can log and carry on rather than crash.
Types ¶
type Action ¶
type Action string
Action names a single convergence step, for structured logging.
const ( // ActionStart starts a fresh container for a replica slot: a plain first start, // or the start half of a zero-downtime roll (the old container keeps serving). ActionStart Action = "start" // ActionStop stops and removes a container immediately: a scale-down, an extra, // a cold Egg or a duplicate. ActionStop Action = "stop" // ActionRestart restarts an up-to-date but crashed container in place. ActionRestart Action = "restart" // ActionRoll drains a superseded (stale or legacy) container gracefully, once a // healthy replacement is already serving: the stop half of a zero-downtime roll. ActionRoll Action = "roll" )
type Plan ¶
type Plan struct {
Steps []Step
}
Plan is the set of steps computed by Diff. A rolling deploy spans more than one plan: an early plan starts the new container (leaving the old serving), and a later plan drains the old once the new is healthy. No single plan ever stops a slot's only healthy backend.
func Converge ¶
Converge is the full diff-then-apply cycle: list actual containers, compute the plan and apply it. It returns the plan (for logging) and any converge errors.
func Diff ¶
func Diff(desired contract.DesiredState, actual []docker.Container) Plan
Diff computes the convergence plan for a desired state against the observed containers. It is pure: it performs no I/O and mutates nothing, which is what makes it unit testable.
Rules, per desired workload with Replicas = N, one replica slot at a time (indices 0..N-1), converging towards one healthy, up-to-date container per slot WITHOUT ever taking the slot's only healthy backend away (zero-downtime rolls):
- No up-to-date container in the slot: START a new one. Any stale (old image or version) or legacy container in the slot is LEFT RUNNING so it keeps serving whilst the new one boots. This is the start half of a start-new-before-stop-old roll, and also the plain first start when the slot is empty.
- An up-to-date container exists and is HEALTHY: the slot is served by new code, so DRAIN the old and legacy containers now (the stop half of the roll), and stop any duplicate up-to-date containers.
- An up-to-date container exists but is still booting: WAIT. The old container (if any) keeps serving; nothing is stopped.
- An up-to-date container has crashed: RESTART it in place.
- A container at an index >= N (a scale-down) is surplus and stopped.
- Replicas == 0 stops every container for the workload (the Egg goes cold).
- A container with no matching desired workload is stopped (extra).
type Step ¶
type Step struct {
Action Action
WorkloadID string
// BlobID is the internal Blob identity of the Egg the step concerns, if
// known. Never rendered to customers.
BlobID string
// ContainerID is the target container, where one exists.
ContainerID string
// ReplicaIndex is the 0-based replica slot this step concerns. ActionStart uses
// it to name and label the new container; stop, roll and restart carry it for
// logging and idempotency.
ReplicaIndex int
}
Step is one planned or performed convergence action, kept for logging and for assertion in tests.