platform: OpenTofu/Ansible für Proxmox, CI, Makefile, Doku-Abgleich

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 00:54:23 +02:00
co-authored by Claude Opus 5.5
parent cb5a413169
commit f22eaa8449
27 changed files with 623 additions and 6 deletions
+21 -2
View File
@@ -15,8 +15,8 @@ Vorgehen pro Baustein: **Spec → Implementierung → Tests → Commit**. Bis zu
| 7 | Portabilität | SPEC-inventory | Inventar-Parser, Katalog, Placement, CLI | ✅ |
| 8 | API | SPEC-core §8 | FastAPI-App, Auth, Metriken | ✅ |
| 9 | Deployment-Artefakte | PLAN §1, §3 | Compose pro Rolle, LiteLLM, Prometheus-Regeln, Alertmanager, n8n-Workflows | ✅ |
| 10 | Plattform | ADR-0001/0002 | OpenTofu (bpg/proxmox), Ansible-Rollen (Treiber-Pinning, Docker) | ✅ (ungetestet gegen echten Cluster) |
| 11 | CI | – | Gitea Actions: Tests, Lint, Compose-Validierung | ✅ |
| 10 | Plattform | ADR-0001/0002 | OpenTofu (bpg/proxmox), Ansible-Rollen (IOMMU/VFIO, ZFS-Replikation, Treiber-Pinning, Xid-Exporter) | ✅ geschrieben, **nicht** gegen echten Cluster/`tofu validate` geprüft |
| 11 | CI | – | Gitea Actions: Tests, Lint, Konfig-Validierung, Compose-Prüfung | ✅ |
## Teststrategie
@@ -25,6 +25,25 @@ Vorgehen pro Baustein: **Spec → Implementierung → Tests → Commit**. Bis zu
- **Artefakt-Tests:** Compose-Dateien, Prometheus-Regeln, LiteLLM-Konfiguration und n8n-Workflows werden strukturell geprüft (YAML/JSON gültig, referenzierte Knoten vorhanden, Slots konsistent zur Registry).
- **Nicht getestet bis zum gemeinsamen Deployment:** echte Modelle, Proxmox-API, Portainer-Aktionen, OpenTofu-Apply.
## Stand der Verifikation
| Was | Wie geprüft |
|---|---|
| Kernlogik (Router, Eskalation, Verifier, Pflege-Agent, Healer, Lifecycle, Placement) | 127 Unit- und Integrationstests (`make test`) |
| Konfiguration (Registry ↔ Skills ↔ LiteLLM ↔ Healer ↔ Policy ↔ Katalog) | `knaster validate` |
| Compose-Dateien | `docker compose config` (`make compose-check`) |
| Prometheus/Alertmanager/n8n-JSON | Strukturtests (`core/tests/test_artifacts.py`) |
| n8n, Portainer | nur lesender Erreichbarkeitstest, nichts deployt |
| OpenTofu, Ansible | nur YAML/Syntax. `tofu validate` und `ansible-lint` stehen noch aus |
## Offene Punkte vor dem Deployment
- Image-Tags pinnen: LiteLLM (`main-stable`) und pve-exporter (`latest`). vLLM-, llama.cpp- und Treiber-Versionen gegen den aktuellen Stand prüfen.
- LiteLLM-Wildcard-Routen (`tier1-general/*`) gegen die eingesetzte Version testen.
- Den n8n Chat-Trigger nach dem Import prüfen (Parameter der Knotenversion).
- `sites/knaster/*`: Hosts, VM-IDs, IPs und PCI-Adressen sind Annahmen und werden durch den Inventarlauf ersetzt.
- Classifier `ticket-kategorie.json` entsteht erst aus gelabelten Fällen (Warnung von `knaster validate`).
## Gemeinsames Deployment (später)
1. Inventarlauf auf allen Nodes → `sites/knaster/inventory.yaml` ergänzen → `knaster placement plan`
+8 -1
View File
@@ -75,7 +75,8 @@ Ablauf:
7. **Stufe 3/2:** Classifier bzw. Programm, ohne Slot.
8. **Stufe 1:** Slot des Skills, falls verfügbar, sonst dessen `fallbacks`. Ist keiner verfügbar, wird mit `slot_unavailable` auf Stufe 0 geroutet.
9. **Token-Budget** (§4): erst `full` versuchen, dann `compact`, dann die Fallback-Slots mit größerem Kontext. Passt nichts, wird mit `context_exceeded` auf Stufe 0 geroutet. Passt es auch auf Stufe 0 nicht, ist das Ergebnis ein Fehler `too_large` mit dem Signal `needs_split`.
10. **Adapter:** Wenn `slot.supports_lora`, `skill.adapter == auto` und ein aktiver Adapter für `(slot.base_model, skill.cluster)` existiert, wird `model = adapter.name` gesetzt, sonst `model = slot.litellm_model`.
10. **Adapter:** Wenn `slot.supports_lora`, `skill.adapter == auto` und ein aktiver Adapter für `(slot.base_model, skill.cluster)` existiert, wird `model = "<slot.litellm_model>/<adapter.name>"` gesetzt (LiteLLM-Wildcard-Route auf den vLLM des Slots), sonst `model = slot.litellm_model`.
11. **Canary:** Hat der Slot im Laufzeitzustand ein `canary_model` (vom Lifecycle gesetzt), geht der Anteil `canary_share` der passenden Anfragen auf den Kandidaten. Bei Adapter-Kandidaten gilt das nur für den Cluster des Kandidaten. Die Entscheidung trägt dann `canary: true`.
`escalate(decision, reason)`:
- Bei Infrastruktur-Fehlern (`endpoint_error`, `context_overflow`) wird auf derselben Stufe der nächste Fallback-Slot genommen, sonst wird eine Stufe höher gegangen.
@@ -135,5 +136,11 @@ Ergebnis ist `VerifyResult{passed, checks[{type, passed, detail}]}`. Bei Format
| GET/POST | `/v1/lifecycle/candidates` | Kandidaten (SPEC-lifecycle) |
| POST | `/v1/lifecycle/candidates/{id}/report` | Ergebnis eines Jobs melden |
| POST | `/v1/skills/{name}/graduate` | Graduierungslauf mit mitgelieferten Varianten |
| POST | `/v1/skills/reload` | Skill-Dateien neu laden (nach Git-Pull) |
| POST | `/v1/maintenance/proposals/{seq}/approve` bzw. `/reject` | Freigabe per Knopf (n8n/UI) statt per Prompt |
## 9. Canary-Prober (`knaster.canary`)
Läuft im Service-Prozess (`KNASTER_CANARY_INTERVAL`, Standard 60 s, 0 = aus). Er prüft jeden Slot außer Stufe 0 und Rerank mit einer Mini-Anfrage („Antworte nur mit OK“) bzw. einem Embedding. Daraus entstehen die Metriken `knaster_slot_endpoint_up`, `knaster_slot_canary_ok` und `knaster_slot_canary_latency_seconds`, jeweils mit den Labels `slot, node, docker_host, container, pve_node, vmid` aus `ops` der Registry. Daraus leiten sich die Alerts `SlotEndpointDown` und `SlotCanaryFailing` für den Healer ab.
Authentifizierung: Header `Authorization: Bearer <KNASTER_API_TOKEN>` auf allen `/v1/*`-Pfaden.