feat: multi-node clustering (register, heartbeat, remote trigger, cluster dashboard) #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/clustering-phase1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Turns Baktainer from a single instance into a coordinated cluster. A main instance runs the UI and aggregates status across servers; node instances register with it, back up their own Docker host on their own labels/schedule, and report up. Main observes and can trigger a backup on any node — it never reaches into a node.
All communication is node-initiated (register → heartbeat → long-poll for commands → push events), so nodes may sit behind NAT. TLS is expected from a reverse proxy (Traefik); the app authenticates with a shared join token and per-node bearer tokens over it.
Delivered in three self-contained commits:
Phase 1 — foundation (
6d4f155)BT_CLUSTER_ROLE(standalone/main/node),BT_CLUSTER_JOIN_TOKEN,BT_MAIN_URL,BT_NODE_NAME,BT_HEARTBEAT_INTERVAL+ validation.nodes+cluster_identitytables;backup_historygainsnode_id/node_name(guardedPRAGMA/ALTERshim — no migration framework).secure_compare, revocation + auto re-register on 401.Authorization: Bearerparsing scoped to/api/cluster/*, above theauth_enabled?short-circuit./nodespage +GET /api/nodes.Phase 2 — command channel + remote trigger (
9824b89)node_commandsqueue;queue_commandwakes a per-node condvar so a parked long-poll delivers near-instantly (lost-wakeup-safe). Concurrent polls capped by a semaphore (:busy→204).BT_HEALTH_MAX_THREADS=16; default was 5) since each long-poll holds a thread. New:BT_COMMAND_POLL_TIMEOUT=25,BT_MAX_LONGPOLL=12.GET …/commands(long-poll 200/204),POST …/events(records node-tagged backups + command results + alerts).run_backupvia the existingrun_backup_now, pushes backup + result events.POST /api/nodes/:id/run-backup(session auth, write role; self-node runs locally).Phase 3 — cluster dashboard (
f712d1d)NodeRepository#cluster_summary,BackupHistoryRepository#recent_for_node; snapshot gains acontainers[]list.GET /api/nodes/overview(aggregate tiles + success rate),GET /api/nodes/:id(parsed snapshot + alerts),GET /api/nodes/:id/backups./nodesreworked into overview tiles + clickable grid + per-node drill-down (status/disk/containers/recent-backups/alerts).Testing
Full suite 1061 examples, 0 failures, 3 pending. Added unit + request specs for repos, coordinator, agent (webmock), and every endpoint; plus three in-process end-to-end smokes (one per phase) exercising the real stack — register → heartbeat → command long-poll → execute → node-tagged history → overview/drill-down. README documents the roles and all new env vars.
Out of scope (future)
Remote file browse/download/restore proxied through main.
🤖 Generated with Claude Code