Betrieb: Umstieg aufs Image vollzogen, Binary-Weg eingestellt
This commit is contained in:
+46
-22
@@ -18,12 +18,12 @@ keine Format-Übersetzung — alle Upstreams sprechen OpenAI-Format.
|
||||
|
||||
| Was | Wo |
|
||||
|---|---|
|
||||
| Router (`llmrouter`) | LXC **185020** (`llmlite`, `10.18.5.20`) auf `s18p1`, systemd-Unit `llmrouter`, Port **4010** |
|
||||
| Router (`llmrouter`) | LXC **185020** (`llmlite`, `10.18.5.20`) auf `s18p1`, **OCI-Container** `llmrouter_llmrouter_1` (podman-compose, systemd-Unit `llmrouter`), Bild `git.42i.org/spine/llmrouter:latest`, Port **4010** |
|
||||
| Alter Port **4000** | seit 2026-09-07 von Caddy auf 4010 geleitet (vorher LiteLLM). Hart verdrahtete Clients — Agenten-Images, spark-desktop, ältere Skripte — laufen darüber weiter |
|
||||
| LiteLLM | **abgeschaltet am 2026-09-07** (`systemctl stop/disable llmlite`). Dateien und Container liegen unangetastet in `/srv/llmlite`, letzte Kosten-Datenbank als `spend-final-20260907.sql.gz` |
|
||||
| Caddy (`llm.lan`, TLS über `acme.lan`) | derselbe LXC, **eigener oci-Dienst `caddy`** (`/srv/caddy`, systemd-Unit `caddy.service`), `reverse_proxy localhost:4010` |
|
||||
| Dateien | `/srv/llmrouter/`: Binaries `llmrouter`, `llmrouter-resolve`, `llmrouter-stats`, `llmrouter-keys`; `config.json`, `key-acls.json`, `model-blocklist.json`; `keys.json` (Token → Name, 0600); `.env` (0600); `log/` |
|
||||
| Docker-Image (Demo/Basis) | `git.42i.org/spine/llmrouter:latest`, gebaut von CI; `docker compose up` mit `./data`-Mount als Demo |
|
||||
| Dateien | `/srv/llmrouter/`: `compose.yml`, `.env` (0600); Laufzeit unter `data/`: `config.json`, `key-acls.json`, `keys.json` (0600), `model-blocklist.json`, `log/` (requests.jsonl, changes.log, state.json, aa-cache.json). Sidecar-Binaries daneben, werden nicht mehr gebaut (Ersatz: `podman run` aus dem Image, siehe Deploy) |
|
||||
| Docker-Image (Prod) | `git.42i.org/spine/llmrouter:latest`, gebaut von CI — seit 2026-09-09 läuft der Prod-Einsatz darauf |
|
||||
| Lokales Qwen | LLM-Knoten LXC 189080, `10.18.5.30:11507` |
|
||||
| Sprachdienste lokal | `10.18.5.30:8803` (Qwen3-TTS + whisper.cpp), Ollama `:11434` (Embeddings) |
|
||||
| Kira im Prod-RZ (deizo) | `10.6.42.111:8000/8001/8002` über den WireGuard-Peer des LXC |
|
||||
@@ -47,7 +47,7 @@ Claude-Code-Pfad) steht in [referenz.md](referenz.md#namensräume). Kurzfassung:
|
||||
| alles andere | **404** — kein stiller Fallback mehr seit der LiteLLM-Abschaltung |
|
||||
|
||||
Ein Modellwechsel steht in `log/changes.log` (im LXC:
|
||||
`/srv/llmrouter/log/changes.log`).
|
||||
`/srv/llmrouter/data/log/changes.log`).
|
||||
|
||||
## Rollen und Profile — drei Ebenen
|
||||
|
||||
@@ -116,7 +116,7 @@ endpoint"`). Nachmessen: `tools/telefon-latenz.py` in diesem Repo.
|
||||
## Keys und Rechte
|
||||
|
||||
- Client-Token: `keys.json` (Token → Name; im LXC
|
||||
`/srv/llmrouter/keys.json`, in der Docker-Demo `./data/keys.json`). Die
|
||||
`/srv/llmrouter/data/keys.json`, in der Docker-Demo `./data/keys.json`). Die
|
||||
Werte der Personas liegen in OpenBao `agents/<name>/litellm` Feld `key`; es
|
||||
sind **dieselben Token wie bei LiteLLM**. Noch ohne Token im Router:
|
||||
`inka-mx`, `nightjob`, `lab-xo`, `team-copilot` (LiteLLM kennt nur Hashes).
|
||||
@@ -147,9 +147,9 @@ curl -s "http://llm.lan:4010/stats?days=7" \
|
||||
# aktuelle Zuordnung aller Stufen und alt/-Referenzen
|
||||
curl -s http://llm.lan:4010/zuordnung -H "Authorization: Bearer <ADMIN_KEY>" | python3 -m json.tool
|
||||
# einzelne Anfragen / Modellwechsel / Journal
|
||||
ssh s18p1.lan 'pct exec 185020 -- tail -20 /srv/llmrouter/log/requests.jsonl'
|
||||
ssh s18p1.lan 'pct exec 185020 -- cat /srv/llmrouter/log/changes.log'
|
||||
ssh s18p1.lan 'pct exec 185020 -- journalctl -u llmrouter -n 50 --no-pager -o cat'
|
||||
ssh s18p1.lan 'pct exec 185020 -- tail -20 /srv/llmrouter/data/log/requests.jsonl'
|
||||
ssh s18p1.lan 'pct exec 185020 -- cat /srv/llmrouter/data/log/changes.log'
|
||||
ssh s18p1.lan 'pct exec 185020 -- podman logs -l -n 50'
|
||||
```
|
||||
|
||||
Die Antwort trägt `x-llmrouter-model`, damit ein Client sieht, was wirklich
|
||||
@@ -158,25 +158,40 @@ lief. Weitere Log-Wege (SQLite, Stats-Binary): [referenz.md](referenz.md).
|
||||
## Wartung und Deploy
|
||||
|
||||
Quelle dieses Projekts ist dieses Repo (`spine/llmrouter`). Der Prod-Einsatz
|
||||
läuft weiter als statisches Binary im LXC (Stand 2026-09-08); der Umstieg aufs
|
||||
Image ist **geprüft und machbar**, das Rezept steht unten — vollzogen ist er
|
||||
noch nicht.
|
||||
läuft seit dem **2026-09-09 als OCI-Container** im LXC (podman-compose hinter
|
||||
der Unit `llmrouter`, Bild `git.42i.org/spine/llmrouter:latest`, Laufzeitdaten
|
||||
unter `/srv/llmrouter/data/`). **Der alte Binary-Weg ist eingestellt** —
|
||||
Server-Updates nur noch über das CI-Image; die Sidecar-Binaries
|
||||
(`resolve`, `stats`, `keys`) werden nicht mehr gebaut, dafür läuft das
|
||||
Werkzeug aus dem Image (siehe Schritt 3).
|
||||
|
||||
1. Änderung in diesem Repo (Config, Code), committen, pushen. CI baut und
|
||||
published danach `git.42i.org/spine/llmrouter:latest` — für den
|
||||
Binary-Weg irrelevant, aber der Stand, den jede Demo zieht.
|
||||
2. Binaries bauen: `bun run build` (dazu
|
||||
`bun build --compile --target=bun-linux-x64 src/resolver.ts --outfile dist/llmrouter-resolve`).
|
||||
3. Ausrollen: `scp` nach `s18p1`, dann `pct push 185020 <datei> /srv/llmrouter/<datei>.neu`,
|
||||
im LXC `mv`, `chmod 755`, `systemctl restart llmrouter`.
|
||||
4. Nach Config-Änderungen an Stufen oder `alt/`: `rm /srv/llmrouter/log/state.json`
|
||||
published danach `git.42i.org/spine/llmrouter:latest`.
|
||||
2. Im LXC Bild ziehen und Unit neu starten:
|
||||
```sh
|
||||
ssh s18p1.lan 'pct exec 185020 -- podman pull git.42i.org/spine/llmrouter:latest'
|
||||
ssh s18p1.lan 'pct exec 185020 -- systemctl restart llmrouter'
|
||||
```
|
||||
Nach Config-Änderungen an Stufen oder `alt/`: `rm /srv/llmrouter/data/log/state.json`
|
||||
vor dem Neustart, sonst bleibt die alte Zuordnung. Der Erstlauf fährt für jede
|
||||
Stufe die Last-Probe (≈210k Token je Stufe).
|
||||
3. Sidecar-Werkzeuge ohne Binary — Beispiel Tagesstatistik:
|
||||
```sh
|
||||
ssh s18p1.lan "pct exec 185020 -- podman run --rm --env-file /srv/llmrouter/.env \
|
||||
-e LLMROUTER_CONFIG=/data/config.json -e KEYS_FILE=/data/keys.json \
|
||||
-v /srv/llmrouter/data:/data git.42i.org/spine/llmrouter:latest bun src/stats.ts 7"
|
||||
```
|
||||
(analog `src/keys.ts`, `src/resolver.ts`)
|
||||
4. Rollback auf die Binary (Notfall): `podman-compose down` im
|
||||
`/srv/llmrouter`, dann die gesicherte Unit zurück
|
||||
(`cp /etc/systemd/system/llmrouter.service.binary-bak /etc/systemd/system/llmrouter.service`,
|
||||
`systemctl daemon-reload`, `systemctl enable --now llmrouter`) — die flachen
|
||||
Dateien und `log/` liegen unverändert daneben.
|
||||
5. **Caddyfile-Falle:** die Datei ist als Bind-Mount im Container; ein `mv`
|
||||
tauscht den Inode und `caddy reload` sieht die alte Datei. Nach Änderung
|
||||
`oci restart caddy`. Quelle: [caddy/Caddyfile](caddy/Caddyfile).
|
||||
|
||||
### Umstieg aufs Image (geprüft am 2026-09-08, ausstehend)
|
||||
### Umstieg aufs Image (geprüft am 2026-09-08, vollzogen am 2026-09-09)
|
||||
|
||||
Voraussetzungen alle erfüllt: podman 5.4.2 im LXC (kein Docker nötig —
|
||||
Muster wie `caddy.service`: podman-compose + systemd-oneshot), das Image ist
|
||||
@@ -243,9 +258,9 @@ Image danach rückstandsfrei entfernt.
|
||||
|
||||
| Symptom | Prüfen | Tun |
|
||||
|---|---|---|
|
||||
| Agenten bekommen 502/Timeout | `curl http://llm.lan:4010/health`; `systemctl status llmrouter` im LXC | `systemctl restart llmrouter`; Journal lesen |
|
||||
| `… ist noch nicht aufgelöst (503)` | `/zuordnung` leer oder alt | `POST /auffrischen` mit Admin-Key, oder `rm log/state.json` + Neustart; braucht OpenRouter- und AA-Zugang |
|
||||
| 401 für einen Agenten | Journal zeigt `401 … (Key n Zeichen)` | Token fehlt in `keys.json` → mit `keys.ts add --token` nachtragen |
|
||||
| Agenten bekommen 502/Timeout | `curl http://llm.lan:4010/health`; `podman ps` im LXC | `systemctl restart llmrouter`; `podman logs -l` |
|
||||
| `… ist noch nicht aufgelöst (503)` | `/zuordnung` leer oder alt | `POST /auffrischen` mit Admin-Key, oder `rm /srv/llmrouter/data/log/state.json` + Neustart; braucht OpenRouter- und AA-Zugang |
|
||||
| 401 für einen Agenten | `podman logs -l` zeigt `401 … (Key n Zeichen)` | Token fehlt in `data/keys.json` → mit `keys.ts add --token` nachtragen |
|
||||
| 403 `darf … nicht rufen` | `key-acls.json` | Recht ergänzen (versioniert in diesem Repo), Neustart |
|
||||
| Zahlen im TTS falsch gesprochen | Sprechtext-Regel greift nur für PLZ/Nummern | Fish über OpenRouter zerlegt deutsche Beträge/Daten — deshalb Grok Voice bis Fish bei Uwe läuft (live/live#2247) |
|
||||
| `llm.lan` antwortet mit LiteLLM-Fehlern statt Router | Caddy zeigt auf 4000 | Caddyfile prüfen, `oci restart caddy` |
|
||||
@@ -268,6 +283,15 @@ starten — LiteLLM bedient die `2608`-Namen weiter, die `2609`-, `alt/`- und
|
||||
|
||||
## Verlauf
|
||||
|
||||
- 2026-09-09: **Umstieg aufs Image vollzogen.** Prod läuft als OCI-Container
|
||||
(`llmrouter_llmrouter_1`, podman-compose hinter der Unit `llmrouter`, Bild
|
||||
`:latest` von Run #7/e144034). Laufzeitdaten wanderten nach
|
||||
`/srv/llmrouter/data/` (Hausmuster `./data:/data`), `state.json` und
|
||||
`aa-cache.json` mitkopiert — Zuordnung unverändert, keine Auffrischung.
|
||||
Verifiziert: `/health` lokal und über `https://llm.lan` 200, Chat 200.
|
||||
**Der Binary-Deploy-Weg (bun build, scp, pct push) ist eingestellt**;
|
||||
Updates nur noch über CI-Image + `podman pull` + Neustart. Unit-Rollback
|
||||
liegt als `llmrouter.service.binary-bak`.
|
||||
- 2026-09-08: **Umstieg aufs Image geprüft.** Probelauf des CI-Images auf
|
||||
dem LXC neben dem Binary (Port 4011): Konfig-/ACL-/Keys-Parität
|
||||
(`/models` byte-identisch), Chat 200 über beide Wege, Zuordnungs-Refresh
|
||||
|
||||
Reference in New Issue
Block a user