Fleet as a Global, Federated Control Plane
Document format reference: metadocsstackpoliciesdocument-format.kmd
Status
Ratified 2026-05-31 (owner). All five §6 decisions resolved. The single-cluster Fleet (FLEET-011..022) is the foundation; this RFC defines the multi-host / global evolution (capabilities G1–G7). The gate is G1/FLEET-028 (durable state → kdb). Implementation is a multi-epic campaign sequenced in §8.
Implementation status (2026-06-01): the buildable campaign is complete — G1 (FLEET-028), G2 (031), G3 (032), G4 (033), G5 (034), G6 (035), G7 API+profiles (036) all DONE. Remaining: G6b/active-active+cross-region+mTLS (FLEET-037, gated on kdb-RFC-008 multi-region live + a real 2nd region) and the G7 UI (FLEET-038, Flutter web). Cross-host kbox-dump shipping in true multi-node = node-agent proxy (FLEET-027). See
meta/docs/stack/modules/fleet.md.
1. Motivation
Today Fleet is a single-cluster orchestrator: one control plane, one in-memory ResourceStore, scheduling pods onto the nodes of that cluster. The owner's vision is broader: Fleet as a universal compute-orchestration backend that works at three scopes with one API + one UI —
- Local cluster — one host (e.g.
s.khost1), today's scope. - Global / federated — many hosts across sites, Fleet placing a VM/kbox on
the most suitable host, migrating kboxes between hosts for resource rebalancing.
- Managed clusters as a product — a requester asks Fleet not just for a
VMkbox, but for a whole managed cluster of VMskboxes (on one host or spread across hosts) to test HA, load-balancing, and failure modes of the programs they are developing.
…serving both machine consumers (API, automated orchestration) and humans (UI), for both Koder Stack customers and Koder collaborators (with a profile that grants resource monitoring + management).
This is the Kubernetes-federation / Cluster-API problem, built native on the Koder substrate (kbox runtime, lease lifecycle, kdb data plane, Koder ID auth).
2. The single hard blocker: state
The current internal/core.ResourceStore is in-memory (a map guarded by a RWMutex). Everything global depends on replacing it:
- R-STATE-1. Cluster state MUST move to a persistent, consistent backend.
Per
stack-RFC-001(kdb as the unified data plane) the default is kdb-next (orpkg/kdb/PG with RLS today). The store interface stays; the backend swaps. This is the prerequisite for HA control-plane (FLEET-019 leader election only becomes real once the lease + state survive a process, which needs durable storage + quorum — see FLEET-002). - R-STATE-2. Until R-STATE-1 lands, "global" is impossible: two control
planes cannot coordinate over a per-process map. Sequencing: state backend first, federation second.
3. Architecture — three tiers
┌──────────────────────────────────────────┐
│ Global control plane (Fleet "hub") │
│ - durable state (kdb-next, R-STATE-1) │
│ - global scheduler (host selection) │
│ - federation registry (member clusters) │
│ - one API + one UI (RBAC by profile) │
└───────────────┬───────────────┬───────────┘
│ │
┌─────────────▼──┐ ┌──────▼─────────────┐
│ Cluster A (host)│ │ Cluster B (host(s))│ ← member clusters
│ Fleet control │ │ Fleet control │ (today's single
│ + node agents │ │ + node agents │ cluster = a leaf)
│ → kbox runtime │ │ → kbox runtime │
└─────────────────┘ └────────────────────┘- A member cluster is exactly today's Fleet (single control plane + agents
over kbox on one or more hosts). Nothing about the leaf changes conceptually.
- The global hub is a new role of the same binary: it holds the federation
registry, runs the global scheduler, and proxies/aggregates the API + UI across members. A single-host deploy runs hub+member co-located (no new operational burden for the local case — the "global" tier is opt-in).
4. Capabilities this RFC introduces (each a future ticket/epic)
| # | Capability | Depends on | Notes |
|---|---|---|---|
| G1 | Durable state backend (swap in-memory store → kdb) | stack-RFC-001 | THE prerequisite (R-STATE-1). FLEET-002 multi-node consumes it. |
| G2 | Global scheduler — host selection | G1 | Place a VMkbox on the most suitable host (capacity, locality, taints, cost). Extends the existing `internalscheduler` from node-scoped to host-scoped. |
| G3 | kbox live migration between hosts | BOX (CRIU), G1 | kbox already has CRIU checkpoint/restore (BOX); migration = checkpoint on host A → ship → restore on host B, driven by the rebalancer. Pairs with infra-RFC-001. |
| G4 | Resource-rebalancing controller | G2, G3 | Watches per-host load (FLEET-025 telemetry) and migrates (G3) to balance. Honors PodDisruptionBudgets (FLEET-013) + leases (infra-RFC-003). |
| G5 | Managed clusters as a resource (ManagedCluster CRD) |
G1, G2 | A requester creates a cluster of VMs/kboxes (same host or spread) — for HA / load-balancing / chaos testing of their own programs. Reuses CRDs (FLEET-011). |
| G6 | Federation registry + cross-cluster API/UI | G1 | Member-cluster registration, health, and an aggregated read/act surface. |
| G7 | Universal backend: API + UI, profile-based | G1, FLEET-017/020 | One backend for automated (API) and human (UI) management; RBAC profiles distinguish Stack customers vs Koder collaborators (the latter get fleet-wide monitor/manage). |
5. What already exists in the Stack (so this is wiring, not greenfield)
- kbox (
infra/net/box) — the runtime + CRIU checkpointrestoremigrate(the mechanism G3 needs) + per-host process/cgroup visibility (BOX-142).
- koder-lease (infra-RFC-003) — ephemeral-compute lifecycle (TTL, idle reap,
saturation-aware admission). The global scheduler's elasticity layer.
- kdb / kdb-next (stack-RFC-001) — the durable, multi-tenant (RLS) data plane
for G1.
- Koder ID (specsauthoauth-flow) + Fleet RBAC (FLEET-017/020) — the
profile-based authz for G7 (customer vs collaborator).
- Koder Observability (
infra/observe) + FLEET-025 — per-host/-workloadtelemetry feeding the rebalancer (G4).
- Fleet single-cluster core (FLEET-011..022) — the leaf that federates.
6. Decisions deferred to ratification (open questions)
- Consistency model of the global hub — RESOLVED (2026-05-31). Separate the
two planes; do not conflate them:
- Data plane (Fleet state) → delegated to kdb. Fleet's
Store(G1 /FLEET-028) is the only persistence; Fleet writes zero replication code. Multi-region of the data plane is therefore inherited from kdb: single- region today, geo-replicated the moment kdb's RFC-002 (multi-region) lands — "without schema changes" per kdb-RFC-001 Goal 3.
self-hosted-first+reuse-first: the Fleet must never grow its own replication layer that duplicates (worse) what kdb is building. - Geo-readiness from day 1 (FLEET-029). Every Fleet API + stored object
carries a
regiontag from the start (mirrors kdb-RFC-001 Phase 5 "geo- readiness audit"). Near-zero cost now; makes multi-region *additive later without a schema break*. This is the concrete "implement the readiness, not the feature now" step. - Control plane (scheduler/reconcile leadership) → active-passive, leader
per scope via FLEET-019, independent of how many regions kdb spans. Active-active multi-region of the hub (two hubs reconciling the same cluster concurrently) is gated, not on timidity but on two real dependencies: (i) kdb-RFC-008 geo being live, and (ii) a genuine 2nd region + the latency/ conflict/jurisdiction requirements that only real cross-region load defines. Distributed data + centralized-with-failover decision is the safe shape; active-active control planes are where split-brain lives. Revisit per
always-on.kmdwhen (i)+(ii) hold.
- Data plane (Fleet state) → delegated to kdb. Fleet's
> Decision 2026-06-01 (owner, via /k-go fleet) — mature now, don't scramble later.
> The original gate conflated two things; we split them so maturity isn't deferred to
> customer-pressure time:
> - *A) Buildable-now (no real customer / no real 2nd region needed — matures against a
> standby/simulated 2-region substrate):*kdb-RFC-008 single-primary geo (phases
> 8.1 region metadata + mTLS, 8.2 WAL replication, 8.3 read-routing, 8.4 automatic
> failover) and, on the Fleet side, hub↔member mTLS + *egion-complete inherited
> state (→ FLEET-039*. These are real engineering against a second real kdb
> instance (two region tags, netem-injected partition/latency), not theater — so we build
> and chaos-test them now to reach production maturity before the first international
> customer. Substrate: a locally-simulated 2-region setup on s.khost1 (two region-tagged
> LXCs) is the $0 build+chaos substrate; the GCP koder-fleet-geo-us node is right-sized
> on-demand only for occasional real-WAN validation passes (the sole $ decision, deferred
> to the validation phase).
> - (B) Genuinely gated (correctness is empirical — needs real cross-region load):
> active-active multi-primary (two hubs / two kdb primaries on the same shard) — this
> is kdb RFC-009/CRDT (RFC-008 §8.5), beyond single-primary geo. Stays in FLEET-037,
> gated as before.
> kdb-side execution tracked as a carve-out anchor in the kdb backlog (the kdb component is
> under a concurrent session lock; RFC-008 itself is edited by that owner, not here).
- Migration scope. kbox (CRIU) is clear (G3). VM live-migration (QEMU) and
microVM (firecracker, infra-RFC-001 Phase 3) are separate, heavier seams.
ManagedClustertopology DSL (G5) — how a requester declares "3 nodes,anti-affinity across hosts, 1 LB" — likely a CRD schema (FLEET-011).
- Hub/member trust — mTLS + Koder ID service accounts between tiers.
- Tenancy axis at global scope — Fleet namespaces vs. the Stack
Org→Workspace→Project model (RFC-017). Must reconcile before G7 UI.
7. Non-goals (for this RFC)
- Re-implementing the single-cluster primitives (done: FLEET-011..022).
- A bespoke storage engine — G1 reuses kdb (stack-RFC-001), no new substrate.
- Replacing koder-lease — Fleet consumes it, does not absorb it.
8. Sequencing
G1 (durable state) is the gate. Recommended order: G1 → FLEET-002 (multi-node) → G2 (global scheduler) → G6 (federation registry) → G3 (kbox migration) → G4 (rebalancer) → G5 (managed clusters) → G7 (universal UI/profiles). Each is its own epic; this RFC is the umbrella. The monitoring + control epic (FLEET-022..026) is orthogonal and proceeds in parallel — it makes each leaf observableactuatable, which G4G7 then consume globally.
9. Relationship to existing tickets
- FLEET-002 (multi-node + per-tenant namespace isolation) becomes the first
concrete slice of G1+G2.
- BOX-142/143 (process stream + exec/signal) feed G4 (telemetry) and G7 (act).
- infra-RFC-001 (runtime strategy) + infra-RFC-003 (lease) are the
runtime + lifecycle substrate this builds on.