From 28fd0faa65d407f05c5f245535ee287caaeb5c24 Mon Sep 17 00:00:00 2001 From: Lothnic Date: Wed, 5 Aug 2026 13:35:47 +0530 Subject: [PATCH] feat(control): deployable image + docs (control plane & node agents) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meridian-control had no container image and was absent from the docs site. - deploy/control/Dockerfile: builds meridian-control (verified — migrate applies the schema, run serves /healthz, mint-token works in-container). - docs/CONTROL_PLANE.md (in the mkdocs nav under Understand): explains the gateway <-> control <-> node-agents split, references the meridian-node repo, the deploy flow, a production-readiness checklist, and the one deferred item (batched observation writes). - control README points at the image + the new doc. Co-Authored-By: Claude Opus 4.8 --- deploy/control/Dockerfile | 40 +++++++++++++++++ docs/CONTROL_PLANE.md | 90 ++++++++++++++++++++++++++++++++++++++ meridian_control/README.md | 4 ++ mkdocs.yml | 1 + 4 files changed, 135 insertions(+) create mode 100644 deploy/control/Dockerfile create mode 100644 docs/CONTROL_PLANE.md diff --git a/deploy/control/Dockerfile b/deploy/control/Dockerfile new file mode 100644 index 0000000..4929555 --- /dev/null +++ b/deploy/control/Dockerfile @@ -0,0 +1,40 @@ +# meridian-control image (the node control plane). Separate deployable from the +# gateway image at the repo root. Runs the control-plane HTTP server; apply +# Alembic migrations first (`meridian-control migrate`) as an init step. +# +# docker build -f deploy/control/Dockerfile -t meridian-control . +# docker run -e MERIDIAN_CONTROL_DB_URL=postgresql+psycopg://... \ +# -e MERIDIAN_CONTROL_REQUIRE_MTLS=1 \ +# -v meridian-ca:/var/lib/meridian-control/ca \ +# meridian-control migrate +# docker run ... meridian-control run --host 0.0.0.0 --port 8443 +FROM python:3.12-slim-trixie AS builder + +WORKDIR /build +RUN apt-get update && apt-get upgrade -y --no-install-recommends && rm -rf /var/lib/apt/lists/* + +COPY pyproject.toml README.md ./ +COPY meridian/ meridian/ +COPY meridian_control/ meridian_control/ + +RUN python -m venv /opt/venv \ + && /opt/venv/bin/pip install --no-cache-dir --upgrade "pip>=26.1.2" \ + && /opt/venv/bin/pip install --no-cache-dir ".[control]" + + +FROM python:3.12-slim-trixie AS runtime +RUN apt-get update && apt-get upgrade -y --no-install-recommends && rm -rf /var/lib/apt/lists/* \ + && useradd --system --uid 10002 --create-home meridian-control + +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# CA material and (for SQLite dev) the DB live here; mount a volume in production. +RUN mkdir -p /var/lib/meridian-control/ca && chown -R meridian-control /var/lib/meridian-control +ENV MERIDIAN_CONTROL_CA_DIR=/var/lib/meridian-control/ca +WORKDIR /var/lib/meridian-control + +USER meridian-control +EXPOSE 8443 +ENTRYPOINT ["meridian-control"] +CMD ["run", "--host", "0.0.0.0", "--port", "8443"] diff --git a/docs/CONTROL_PLANE.md b/docs/CONTROL_PLANE.md new file mode 100644 index 0000000..b7cc033 --- /dev/null +++ b/docs/CONTROL_PLANE.md @@ -0,0 +1,90 @@ +# Control plane & GPU node agents + +Meridian has two planes that work together: + +- **The gateway** (this repo, the `meridian` package) — the request/traffic plane. + It decides *whether* a backend may receive traffic and routes to it. +- **The control plane** (`meridian-control`, in this repo) + **node agents** + ([`meridian-node`](https://github.com/IMV-IN/meridian-node)) — the fleet plane. + Central `meridian-control` decides *what* should run on each GPU host; the + `meridian-node` agent decides *how* to run it safely on that host. + +> Central Meridian decides **what** should run and **whether** it may receive +> traffic. `meridian-node` decides **how** to make it run safely on one GPU host. + +``` + meridian-node agent ──enroll / mTLS / heartbeat / desired-state / observations──▶ meridian-control + (GPU host) (this repo) + │ + gateway ◀──── GET /admin/projection (routable managed engines) ────────────────────────────┘ +``` + +## meridian-control + +A **separate deployable** from the gateway (it does not import or modify gateway +code). It implements the node control protocol (`contracts/v1` in the +meridian-node repo): approval-gated enrollment with a built-in Ed25519 CA, +epoch-fenced sessions with restore-safe fencing, leases, desired-state +generations, observations, certificate rotation and revocation/CRL, and a +capacity-aware placement selector. State is durable via SQLAlchemy — **SQLite by +default, Postgres via a URL** — so control replicas are stateless. + +See [`meridian_control/README.md`](https://github.com/IMV-IN/Meridian/blob/main/meridian_control/README.md) +for the full endpoint list and the meridian-node `DESIGN.md` for the protocol. + +## Deploy + +`meridian-control` ships its own image (`deploy/control/Dockerfile`), separate +from the gateway image. + +```bash +docker build -f deploy/control/Dockerfile -t meridian-control . + +# 1. Apply the schema (Alembic) — run once per DB / upgrade. +docker run --rm \ + -e MERIDIAN_CONTROL_DB_URL=postgresql+psycopg://user:pass@db/meridian_control \ + meridian-control migrate + +# 2. Serve. Persist the CA directory; enable mTLS in production. +docker run -d --name meridian-control -p 8443:8443 \ + -e MERIDIAN_CONTROL_DB_URL=postgresql+psycopg://user:pass@db/meridian_control \ + -e MERIDIAN_CONTROL_REQUIRE_MTLS=1 \ + -v meridian-ca:/var/lib/meridian-control/ca \ + meridian-control run --host 0.0.0.0 --port 8443 + +# 3. Mint a one-time enrollment token for a node. +docker exec meridian-control meridian-control mint-token --auto-approve +``` + +The gateway consumes `GET /admin/projection` read-only (set `control_plane.url` +in the gateway config; see the projection-sync notes). Node agents are installed +from the [meridian-node](https://github.com/IMV-IN/meridian-node) repo +(systemd units + Dockerfile + example configs in its `deploy/`). + +## Production readiness checklist + +The system is feature-complete and tested (gateway 540, control 41, node 95 unit +tests + real-GPU host tests on an RTX 4060). Before a production rollout: + +- [ ] **Enable mTLS.** `MERIDIAN_CONTROL_REQUIRE_MTLS=1`, terminate mTLS at the + edge, and forward the verified client cert in `x-client-cert`. The app must + be reachable **only** through that edge. (Default is off for dev.) +- [ ] **Use Postgres** (`MERIDIAN_CONTROL_DB_URL`), run `meridian-control migrate` + on deploy, and tune the pool (`MERIDIAN_CONTROL_DB_POOL_SIZE` / + `_MAX_OVERFLOW`). +- [ ] **Persist and back up the CA directory** (`/var/lib/meridian-control/ca`). + Follow the restore runbook (`POST /admin/restore`) after any DB restore so + fencing epochs cannot regress. +- [ ] **Node hosts:** deploy the root helper, pin allowed image digests + trusted + signing keys + per-device capacity in the root-owned policy, and start in + `observe-only` before enabling `managed-host`. +- [ ] **Validate the newer engine drivers** (TGI, SGLang, llama.cpp, LMDeploy) + against real engine images on a host — their launch flags are typed and + unit-tested but not yet run against live engines. + +## What's left (deliberately deferred) + +**Load-driven batched observation writes** beyond ~500 nodes (meridian-node +DESIGN §10.7). Batching trades projection/placement read-freshness for write +throughput, so it should follow a measured load profile rather than a guess. +Connection pooling is the correct first lever and is in place. diff --git a/meridian_control/README.md b/meridian_control/README.md index 30aaf0e..25349df 100644 --- a/meridian_control/README.md +++ b/meridian_control/README.md @@ -34,6 +34,10 @@ Production manages the schema with **Alembic** (`meridian-control migrate`, or `alembic -c meridian_control/alembic.ini upgrade head`). `create_all` remains the zero-config default for local dev and tests. +Container image (separate from the gateway image): `deploy/control/Dockerfile`. +See [docs/CONTROL_PLANE.md](../docs/CONTROL_PLANE.md) for the full deploy flow and +the production-readiness checklist. + ## Endpoints | Method + path | Purpose | diff --git a/mkdocs.yml b/mkdocs.yml index ee6e136..875934a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,6 +77,7 @@ nav: - Known issues: KNOWN_ISSUES.md - Understand: - Architecture and scope: FULL.md + - Control plane & node agents: CONTROL_PLANE.md - Milestones: MILESTONES.md - What's shipped: ship.md - Roadmap: ROADMAP.md