-
Notifications
You must be signed in to change notification settings - Fork 0
Fleet Deployment Colony
How a Theia cluster is deployed and operated in the field: colony provisions
and orchestrates boards over SSH from an S3 runtime plane, and the Ground
Station (GS) drives it from a web UI. This is the production analogue of the
local theia manifest → dist → orchestrate loop — see
Deployment-Manifest-Generation-and-Serialization for that.
The Tutorial walks the whole flow hands-on in Provision + Deploy; this page is the reference model behind it.
Theia splits every deploy into two independent planes:
| Plane | Ships | Delivered by | Verb |
|---|---|---|---|
| Base / runtime | supervisor + platform services (.deb) |
colony (SSH/Ansible) |
provision + orchestrate
|
| App / SWP | the user's Functional Clusters, as an overlay | Mender (OTA) |
theia release-swp → GS deploy |
The runtime is FIXED per install; the app SWP is exchanged freely on top of it (runtime-dependency gated). That split is the whole point: you re-provision to change the base, but swap the app with a one-click Mender deployment.
The framework services manifest declares exactly two roles whose name is the role:
-
master— the coordinator: etcd + every platform singleton (com, per, sm, phm, vucm, …) + the Mender gateway. -
zonal— a zone-of-responsibility worker: the minimal per-board slice (ucm+shwa). It reaches the master's singletons over TIPC and the shared etcd.
One master, N zonal. The framework names no boards — colony fans the one
zonal slice onto every worker board, and each board's runtime identity is
master / zonal-1 / zonal-2 / … (the instance disambiguates the shared role
name). A day-2 user SWP can rename the deployed workers as it wishes.
colony is a registry-free deploy service (the colony-api container behind
the GS). Every deploy fact comes from the request; the runtime .debs and the
per-role manifest come from the S3 runtime plane
(s3://theia-runtime/<version>/), never a local tree.
-
provision— one-time board setup: base dirs, OS packages, etcd, the TIPC bearer, the Mender client, and the Theia OTA update modules (theia-swp/theia-app/theia-release) + state-scripts. -
orchestrate— per-deploy: pull the runtime + services.debs from S3,dpkg -i, lay the release-dir (current → releases/<ver>), push config, reload the supervisor. -
cleanup— the inverse (stop supervisor, remove/opt/theia,dpkg -r).
Always pass role so colony pulls the right manifest/<role>/ slice.
The GS is the operator's web UI. It reads the fleet from Mender + the S3 planes
and fans a Distribution (per-role {abi, runtime_build, swp_build}) out to
the matching boards: base → colony, app → Mender.
Pick a Distribution and the target boards; the GS resolves each board's ABI to the matching build and dispatches.

theia release publishes the runtime plane; theia release-swp the app plane.
The GS catalogs both.

Every enrolled rig, its base runtime, app SWP, and health.

A new board SSH-probes into the fleet and dual-registers (colony + Mender).

The GS fans the Distribution out; the Action History shows each per-board Orchestrate / Provision / SWP action with a cancel control and a live status.



colony-api listens on :8081 inside the GS docker network. The GS (and the
theia MCP colony_deploy tool) drive it:
POST /deployments {rig, kind, host, extra} → {id, status, …}
GET /deployments/{id} status + statistics
GET /deployments/{id}/log the Ansible output
POST /deployments/{id}/abort abort a pending/scheduled run
kind ∈ {provision, orchestrate, cleanup}; host = "ip[:port]"; role,
runtime_version, machine_instance, etcd_external ride in extra. Poll the
id until status is finished; success = statistics.status.success > 0 && failure == 0.
-
ansible_connectioninheritance. colony resolves the target in ahosts: localhostplay thenadd_hosts the board. The add_host reads a DEDICATEDtarget_connectionvar (defaultssh) — NOTansible_connection, which is alreadylocalin the localhost play and would make every board task run ON THE CONTROLLER. The docker-test-rig path overrides with-e target_connection=community.docker.docker. -
Machine instance is a DEPLOY fact. The N zonal workers share the name
zonal; their distinct TIPC instances (1, 2, …) come from themachine_instancecolony passes, persisted on-device so an OTA relaunch recovers the same instance instead of colliding at 0. -
Safe-base HW gating. The serialized manifest carries
deploy/config/master/executor.jsonmarking hardware-dependent FCs (fw/tsync/rds)run_on_start: false, so the runtime deploys cleanly on ANY rig regardless of HW/CAPA. An operator whose target has the subsystem re-enables it with a per-target override.
deploy/docker-compose.yml runs theia-{central,compute,frontal} + a
theia-etcd sidecar (theia rig up) as network_mode: host SSH rigs
(:2201 / :2202 / :2203), which colony provisions over SSH — the local mirror of a
real fleet. Drive the whole flow against it, exactly as the Tutorial does.