Files
cluster-knaster/docs/BETRIEB.md
T
2026-10-14 19:11:52 +02:00

20 KiB
Raw Blame History

Betrieb: Skill-Lebenszyklus, Hermes, Pflege, Freischaltung, Proxmox-Cluster

1. Lebenszyklus eines Skills

          Hermes schreibt SKILL.md
                   │
                draft ──(Mensch/Agent: aktivieren)──▶ active, Stufe 0
                                                        │  läuft auf dem starken Modell mit Skill-Text,
                                                        │  sammelt verifizierte Fälle
                     Service-Routine: stabil ≥ 95 % ────┤
                                                        ▼
                                            request_graduation (Freigabe)
                                                        │  Hermes erzeugt Varianten →
                                                        │  POST /v1/skills/{name}/graduate
                                                        ▼
                                  promote_skill (Freigabe) ──▶ active, Stufe 1 (schwaches Modell)
                                                        │
                    Drift (Pass-Rate < 80 %) ──▶ demote_skill (automatisch) ──▶ demoted (Stufe 0)
                                                        │
             ≥ 300 Trainingsfälle, Stufe-1-Rate < 90 % ─▶ train_adapter (Freigabe) ──▶ Lifecycle-Pipeline

Stufe 2 (Programm) und Stufe 3 (Classifier) gibt es, wenn der Skill execution: program|classifier deklariert und die passende Stufe freigegeben ist. Programme liegen in knaster/programs.py und gehen wie normaler Code durch ein Review. Classifier entstehen aus gelabelten Fällen (EmbeddingClassifier.train) und liegen unter config/classifiers/<name>.json.

2. Rolle von Hermes

Hermes läuft als Skill-Autor mit dem starken Modell. Er zeigt auf LiteLLM, Alias tier0-strong. Hermes steht nicht im Pfad jeder Anfrage.

Auslöser Hermes tut Schnittstelle
Job graduate_skill (über n8n knaster-jobs) 10–30 realistische Varianten erzeugen, Graduierung aufrufen. Schlägt sie fehl, den Skill anhand von failures überarbeiten POST /v1/skills/{name}/graduate
Job merge_skills zwei Skills zu einem zusammenführen, alten Skill auf retired setzen Git-Commit in skills/, dann POST /v1/skills/reload
Neue Aufgabenklasse (häufige no_skill-Fälle) neuen SKILL.md-Entwurf schreiben (status: draft) Git-Commit + Reload

Skills sind Dateien im Repo. Jede Änderung ist dadurch ein nachvollziehbarer Commit und lässt sich zurückdrehen.

3. Pflege per Prompt (Beispiele)

> routine
Service-Routine
Befunde:
- Drift: zusammenfassung Pass-Rate 72% (n=40)
Automatisch erledigt:
- P-12: Skill zusammenfassung auf Stufe 0 zurückstufen → Skill zusammenfassung auf Stufe 0 zurückgestuft
Offene Vorschläge (genehmige P-x / lehne P-x ab):
- P-13 [low] LoRA-Adapter für rechnungen trainieren – 412 verifizierte Fälle, Stufe-1-Rate 86%

> genehmige P-13
P-13 executed: Kandidat 7f3e… (adapter) angelegt und Build gestartet

> wechsle tier1-general auf qwen3-32b-awq
Vorschlag P-14 [medium] Basismodell von tier1-general auf qwen3-32b-awq wechseln …
Bestätige mit „genehmige P-14“.

Freitext, der keinem Befehl entspricht, bildet ein kleines Modell auf einen Befehl ab. Der Agent fragt dann mit „Meinst du …?“ zurück.

4. Dry-Run aufheben (schrittweise)

  1. Eine Woche mit KNASTER_DRY_RUN=true laufen lassen. Die Healer-Ergebnisse stehen als [dry-run] … in den Antworten bzw. Logs.
  2. KNASTER_DRY_RUN=false setzen. Interne Aktionen (Slot-Status, Skill-Stufen, Kandidaten) liefen schon vorher. Jetzt werden auch Jobs per Webhook verschickt.
  3. Infrastruktur-Aktionen einzeln freischalten, über config/healer-rules.yaml → enabled_actions: [restart_container], später restart_vm. reboot_host bleibt freigabepflichtig (Policy) und läuft nur im Wartungsfenster.

5. Rollback-Wege

Was Wie
Adapter/Basismodell Prompt rollback <slot> → Freigabe
Skill-Stufe Prompt stufe <skill> zurück bzw. Git-Revert der SKILL.md
Treiber/Engine Proxmox-Snapshot der GPU-VM (vor jedem Update anlegen)
Konfiguration Git-Revert und Neustart des Router-Containers

6. Proxmox: Updates und Neustarts (rollierend, Knoten für Knoten)

Stand 12.10.2026, getestet mit dem Wartungsmodus auf pve44. Gilt für pve44, pve46, pve48, pve52 und pve61.

Wichtig vorab

  • Auf den GPU-Knoten gehört die M4000 (Boot-Grafik) der VM. Nach dem frühen Start bleibt der lokale Bildschirm schwarz. Zugang nur per SSH oder Weboberfläche; das GRUB-Menü ist beim Start noch sichtbar (Notzugang: Eintrag bearbeiten, initcall_blacklist=sysfb_init entfernen).
  • pve61 hängt am Netz nur über die USB-NIC im Dock. Neustart nur, wenn jemand vor Ort ist. Kommt er nach etwa 2 Minuten nicht zurück: Dock aus- und wieder einstecken.
  • Nie zwei Knoten gleichzeitig. Mit 5 Stimmen bleibt das Quorum bei einem fehlenden Knoten erhalten.

Ablauf je Knoten

  1. Vorher: pvecm status (Quorate: Yes), ha-manager status, pvesr status (alle Jobs OK).
  2. Wartungsmodus: ha-manager crm-command node-maintenance enable <knoten>. HA-Gäste ziehen um (infra: Test 36 s nach pve48).
  3. GPU-VM des Knotens sauber stoppen: qm shutdown <vmid> (244/246/248/252). Sie hat kein HA und kann nicht wandern (Passthrough).
  4. Update: platform/proxmox/scripts/bootstrap-node.sh <knoten> vom Laptop (idempotent, meldet Neustart nötig), dann reboot.
  5. Nachher prüfen: Kernel, systemctl --failed, ip -br a show vmbr0, NTP; auf GPU-Knoten lspci -nnk -d 10de: → überall vfio-pci.
  6. GPU-VM startet von selbst (onboot). Danach auf ops: cd /root/cluster-knaster/platform/proxmox/tofu && . /root/.config/knaster/tofu.env && bash ../scripts/refresh-vm-access.sh (DHCP-Adressen können wechseln, Hostschlüssel kommen über den Gast-Agenten) und ansible gpu_vms -m shell -a "nvidia-smi -L".
  7. Wartungsmodus aus: ha-manager crm-command node-maintenance disable <knoten>. HA holt infra auf seinen Heimatknoten pve44 zurück (Test 41 s).

GPU-VMs aktualisieren

  • Pakete per apt in der VM, die NVIDIA-Pakete sind auf hold (R580). Vor Treiberwechseln einen Snapshot anlegen: qm snapshot <vmid> vor-treiber.
  • Nach einem VM-Neustart immer refresh-vm-access.sh, solange es keine DHCP-Reservierungen gibt (D5).

7. Infra-Stack und Monitoring (LXC infra)

Stand 12.10.2026 (Task 5.2). Der LXC infra (vmid 101, HA, Heimat pve44, Replikation nach pve48/pve52) führt einen Compose-Stack knaster-infra: Router (Dry-Run), TTS (Piper), Postgres, Prometheus, Alertmanager, Grafana, pve-exporter, node-exporter, autoheal. Kein eigener LiteLLM (D4).

Adressen (DHCP, die IP kann sich nach einem Umzug ändern; aktuelle IP: ansible infra -m debug -a var=ansible_host auf ops oder refresh-vm-access.sh)

Dienst URL Anmeldung
Grafana http://<infra-IP>:3000 admin bzw. kiosk (Viewer)
Prometheus http://<infra-IP>:9090 ohne (nur LAN)
Alertmanager http://<infra-IP>:9093 ohne (nur LAN)
Router http://<infra-IP>:8080 Bearer-Token

Wo liegt was

  • Konfiguration im Repo: deploy/compose/infra, deploy/prometheus, deploy/alertmanager, deploy/grafana (Datasource, Dashboards). Im LXC als Kopie unter /opt/knaster/repo (wird bei jedem Ansible-Lauf abgeglichen, dort nichts ändern).
  • Geheimnisse nur im LXC, nie im Repo: /opt/knaster/infra/.env (0600) mit POSTGRES_PASSWORD, KNASTER_API_TOKEN, GRAFANA_ADMIN_PASSWORD, GRAFANA_KIOSK_PASSWORD (beim ersten Lauf mit openssl rand erzeugt, danach nie überschrieben). Lesen: ssh root@<infra-IP> grep ^GRAFANA_KIOSK_PASSWORD= /opt/knaster/infra/.env (für den Kiosk, Task 5.3).
  • /opt/knaster/infra/secrets/router_token (Kopie von KNASTER_API_TOKEN für den Alertmanager) und secrets/pve-exporter.env (Kopie von ops /root/.config/knaster/pve-exporter.env, Token monitoring@pve!prom, PVEAuditor).
  • Einstellungen ohne Geheimnis (Dry-Run, LITELLM_BASE_URL …) stehen in platform/proxmox/ansible/roles/infra-stack/defaults/main.yml und werden bei jedem Lauf in die .env geschrieben.

Ausrollen (auf ops, idempotent): cd /root/cluster-knaster && git pull, Adressen auffrischen (Abschnitt 6, Schritt 6), dann in platform/proxmox/ansible:

  • ansible-playbook playbooks/monitoring.yml – Exporter in den GPU-VMs (ohne Treiber-Rolle, kein Neustart) und Stack im LXC.
  • Ein Image-Update heißt: Tag im Compose-File ändern, committen, Playbook laufen lassen.

Ziele der GPU-VMs (file_sd) auffrischen Die GPU-VMs haben DHCP-Adressen (D5). platform/proxmox/scripts/monitoring-targets.py schreibt aus tofu output -json gpu_vms und der Registry node.json und gpu.json (Labels instance = VM-Name, pve_node, vmid, slot, slots). Nach jedem VM-Neustart:

cd /root/cluster-knaster/platform/proxmox/tofu && . /root/.config/knaster/tofu.env && bash ../scripts/refresh-vm-access.sh
cd ../ansible && ansible-playbook playbooks/monitoring-targets.yml

Prometheus liest die Dateien in /opt/knaster/infra/file_sd selbst neu, ein Neustart ist nicht nötig.

Exporter in den GPU-VMs: prometheus-node-exporter (Port 9100, Ubuntu-Paket, liest /var/lib/node_exporter/textfile mit den Xid-Zählern) und nvidia_gpu_exporter (Port 9835, nvidia-smi; DCGM unterstützt Maxwell nicht). ufw-Regeln mit Kommentar knaster-monitoring erlauben beide Ports aus 192.168.100.0/24; ufw selbst wird von der Rolle nicht ein- oder ausgeschaltet.

Alerts: Alertmanager meldet an den Router (/v1/healer/alertmanager, Healer im Dry-Run). Der Receiver für n8n knaster-notify ist in deploy/alertmanager/alertmanager.yml nur vorbereitet (auskommentiert). Test: docker exec knaster-infra-alertmanager-1 amtool --alertmanager.url=http://localhost:9093 alert add test severity=warning und … alert query.

Dashboards (Ordner knaster, Startseite „knaster – Übersicht“): Proxmox via Prometheus (grafana.com 10347), Node Exporter Full (1860), Nvidia GPU Metrics (14574), knaster – Übersicht (eigenes).

Achtung HA-Umzug und ZFS-Seiten-Cache (gefunden 12.10.2026 bei der HA-Probe) Nach zfs receive (Replikation) liefert ein Knoten für Dateien, die dort früher per mmap geöffnet waren, weiter den alten Inhalt aus seinem Seiten-Cache (ZFS 2.4.4, Kernel 7.0.14; Beleg auf pve44: zfs diff <snap> leer, written 0, md5 der Datei trotzdem ungleich der im Snapshot). Folge beim ersten Umzug nach pve48: dockerd las veraltete bbolt-Datenbanken, brach mit panic: invalid freelist page ab, danach fehlten Netzwerk und Volume-Labels. Betroffen ist jeder replizierte LXC mit mmap-Nutzern (Docker, Prometheus-TSDB, später grp-test), sobald er auf einen Knoten zurückkehrt, auf dem er schon lief.

  • Schutz im Container: Dienst knaster-drop-stale-cache.service (Rolle infra-stack) verwirft vor containerd/docker per posix_fadvise(DONTNEED) den Cache aller Dateien des Containers. Protokoll: journalctl -u knaster-drop-stale-cache -b (zeigt geänderte Datenbank-Prüfsummen).
  • Eine Lösung auf den Knoten (OpenZFS-Fehler melden bzw. Update, Hookscript) entscheidet der Nutzer.

Wiederherstellung, falls Docker nach einem Umzug nicht startet (im LXC, nichts löschen):

  1. systemctl stop docker containerd; journalctl -u docker -b | grep -A12 panic zeigt die betroffene Datenbank (z. B. buildkit/cache.db).
  2. Die defekte Datenbank bzw. das Verzeichnis beiseiteschieben, z. B. mv /var/lib/docker/buildkit /var/lib/docker/buildkit.defekt-<datum>.
  3. systemctl start docker, dann docker compose -p knaster-infra --env-file /opt/knaster/infra/.env -f /opt/knaster/repo/deploy/compose/infra/docker-compose.yml up -d --force-recreate (Volumes bleiben, kein down -v).
  4. Danach auf ops ansible-playbook playbooks/monitoring.yml --limit infra.

8. Zugang: Benutzer, Rollen, 2FA, Token (Phase 4.1/4.2)

Stand 13.10.2026, Quelle sites/knaster/proxmox.yaml (access), ausgerollt mit playbooks/cluster.yml (Rolle pve-cluster).

Konto Zweck Rechte Geheimnis liegt
r.rapp@pve persönlicher Admin (Weboberfläche) Gruppe admins = Administrator auf / Passwort PVE_ADMIN_R_RAPP_PASS in it/proxmox/.env; Passwort, TOTP und Recovery-Keys in Password Depot (Datei tfa-r.rapp.txt am 13.10. gelöscht)
root@pam Notfallzugang, SSH-Schlüssel, Ansible alles Passwörter PVExx_PASS in .env, Schlüssel keys/id_ed25519_pve
tofu@pve!ops OpenTofu auf ops VM-, Storage-, Mapping-, Pool-Rechte ops /root/.config/knaster/tofu.env
monitoring@pve!prom pve-exporter PVEAuditor ops /root/.config/knaster/pve-exporter.env, Kopie in infra
healer@pve!knaster Healer (SPEC-healer) Rolle KnasterHealer (VM.PowerMgmt, VM.Audit) nur auf /pool/gpu ops /root/.config/knaster/healer.env
  • Anmeldung Weboberfläche: Benutzer r.rapp, Realm „Proxmox VE authentication server“, danach TOTP-Code. Die Recovery-Keys gelten je einmal.
  • TOTP: liegt in Password Depot (Feld „Einmalpasswort / 2FA“). Für neue Konten schreibt pve-admin-user.sh eine Datei tfa-<name>.txt; Secret und Recovery-Keys daraus in Password Depot übernehmen und die Datei löschen.
  • Anmeldung und Vertretung: docs/ANMELDUNG.md (auch Browser-Falle: Bitwarden-Leiste blockiert den TOTP-Dialog, Inkognito oder Domain ausschließen).
  • Neues Admin-Konto: Name in access.admin_users eintragen, playbooks/cluster.yml auf ops, dann vom Laptop platform/proxmox/scripts/pve-admin-user.sh <name> (setzt Passwort, TOTP, Recovery-Keys; idempotent).
  • 2FA für root@pam ist bewusst nicht gesetzt: root bleibt Notfallzugang und läuft über SSH-Schlüssel. Wenn gewünscht, gleiches Vorgehen über pvesh create /access/tfa/root@pam – vorher den Code in einer App haben, sonst sperrt man sich aus der Weboberfläche aus (SSH bleibt).
  • Token rotieren: pveum user token remove <user> <token>, Datei auf ops löschen, Playbook erneut (Healer) bzw. Token neu anlegen und Datei schreiben (tofu, monitoring).
  • Verloren gegangenes TOTP: pvesh get /access/tfa/<user> listet die Einträge, pvesh delete /access/tfa/<user>/<id> entfernt sie, danach das Skript erneut.

9. Benachrichtigungen (Phase 4.3)

Ziel knaster-mail (Sendmail an ki@mygodel.de, aus access.mail_to), Matcher knaster-alles ohne Filter (Backup, Fencing, Replikation, Paket-Updates), default-matcher abgeschaltet (sonst doppelt). Postfix auf den Knoten liefert direkt an die MX von mygodel.de (13.10. getestet: 250 … Queued mail for delivery). Kein SMTP-Relay, keine Zugangsdaten.

  • Test: pvesh create /cluster/notifications/targets/knaster-mail/test auf einem Knoten, Zustellung im Journal: journalctl -u postfix --since -10min | grep status=.
  • Landet die Mail im Spam: Absender root@pveXX.buero-godel.local hat kein SPF. Dann in Exchange Online eine Transportregel oder einen Connector für die Knoten-IPs anlegen.
  • Empfänger ändern: access.mail_to in der Site-Datei, dann pvesh set /cluster/notifications/endpoints/sendmail/knaster-mail --mailto <adresse> (das Playbook legt nur an, es ändert bestehende Ziele nicht).

10. Firewall (Phase 4.4)

Datacenter-Firewall aktiv auf allen Knoten (/etc/pve/firewall/cluster.fw, Vorlage roles/pve-cluster/templates/cluster.fw.j2). Eingehend DROP, ausgehend ACCEPT.

  • IPSET admin: die fünf Knoten, Admin-Laptop .151 (WLAN) und .181 (USB-LAN im Dock), appsrv08 .29, ops .173, infra .188. Nur diese erreichen 22, 8006, 3128, 5900–5999 und 60000–60050. Alle anderen Adressen im LAN bekommen auf diesen Ports DROP, Ping aus dem LAN geht. Corosync zwischen den Knoten erlaubt Proxmox selbst.
  • Warum eigene Regeln statt IPSET management: Proxmox ergänzt management immer um das lokale Netz (local_network, hier das ganze /24). Eine Einschränkung auf einzelne Adressen wirkt deshalb nur mit ACCEPT für +admin und anschließendem DROP für das /24 (13.10. geprüft: aus einer GPU-VM sind 22 und 8006 zu, vom Laptop und aus infra offen).
  • DHCP-Risiko (D5): Seit 14.10. haben ops (.173) und infra (.188) feste Adressen (infra über containers.infra.ip in der Site-Datei und tofu, ops per pct set 100 -net0 …ip=… auf pve46; DNS .120, Suchdomäne buero-godel.local). Am DC sind sie noch nicht reserviert, der Support soll die Reservierungen nachziehen (Task 0.2). Nur der Laptop (WLAN .151, Dock .181) hängt noch am Lease. 14.10. passiert: Laptop kam per Dock mit .181 und war ausgesperrt, Rückweg über ops hat funktioniert. Wechselt eine Adresse, ist diese Quelle ausgesperrt. Rückweg: von einer noch zugelassenen Adresse (z. B. ssh ops, dann ssh pve44) die Adresse in sites/knaster/proxmox.yaml ändern und das Playbook laufen lassen, oder direkt cluster.fw bearbeiten. Letzter Rückweg: Konsole am Knoten, dort pve-firewall stop bzw. enable: 0 in cluster.fw.
  • Totmannschalter: Das Playbook stellt bei jeder Änderung einen Timer (knaster-fw-totmann, 600 s), der enable: 0 schreibt, und hebt ihn erst nach erfolgreicher Prüfung (SSH und 8006 zu allen Knoten von ops aus) wieder auf. Bricht der Lauf ab, geht die Firewall von selbst wieder aus.
  • Neue Verwaltungsquelle (z. B. zweiter Laptop): Eintrag unter firewall.management, Playbook laufen lassen.
  • Gast-Firewalls (VM/LXC) sind nicht aktiviert; die GPU-VMs schützen ihre Ports mit ufw (Abschnitt 7).

11. Zertifikat der Weboberfläche (Phase 4.6)

Die Knotenzertifikate stammen von der Cluster-CA (/etc/pve/pve-root-ca.pem, gültig bis 2036) und enthalten die IP-Adresse als SAN. Es reicht, die CA einmal auf dem Laptop als vertrauenswürdig einzutragen, dann sind https://192.168.100.2xx:8006 für alle fünf Knoten ohne Warnung erreichbar.

  • Kopie der CA: it/proxmox/pve-root-ca.pem (SHA-256 A2:71:C0:AB:…:77:3E, zum Abgleich openssl x509 -in … -noout -fingerprint -sha256).
  • Import ohne Adminrechte (Benutzerspeicher, Windows fragt einmal nach): certutil -user -addstore Root C:\Users\r.rapp\it\proxmox\pve-root-ca.pem. Danach Browser neu starten.
  • Kein ACME/Let's Encrypt: die Knoten haben keine öffentlichen Namen (IP-Regel, kein DNS).

12. Netzwerk-Prüfung (Stand 13.10.2026)

Knoten NIC Treiber Link Bridge
pve44, pve46, pve48, pve52 Intel onboard nic0 e1000e 1 GBit/s vmbr0 → nic0, kein VLAN-aware
pve61 USB-NIC im Dock enx3ce1a1c0839d r8152 1 GBit/s vmbr0 → USB-NIC, ein Link-Reset seit Start
  • Keine e1000e-Hänger („Detected Hardware Unit Hang“) im Kernel-Log. Sollten sie auftreten: ethtool -K nic0 tso off gso off als bekannter Ausweg, dann in /etc/network/interfaces festhalten.
  • VLAN: nicht aktiviert (Global Constraint „vorerst kein VLAN“). Wenn nötig: bridge-vlan-aware yes und bridge-vids 2-4094 auf vmbr0, ifreload -a; auf pve61 nur vor Ort (USB-NIC).
  • Eine zweite NIC für ein getrenntes Corosync- oder Migrationsnetz gibt es auf keinem Knoten. Migration läuft secure über das LAN.
  • Feste Adressen: Knoten sind statisch, Gäste und Laptop per DHCP (D5 offen, Task 0.2). Erst mit Reservierungen ist die Firewall-Liste dauerhaft stabil.

13. Testvorgehen

platform/proxmox/scripts/healthcheck.sh (Laptop oder ops, nur lesend) prüft in einem Lauf: Quorum und Stimmen, HA-Dienste, Replikation, Firewall aktiv und Regel +admin, Matcher, Benutzer und 2FA; je Knoten Kernel, fehlgeschlagene Dienste, Knoten-Firewall, NTP, vmbr0, Platz auf /, tank, Zertifikatslaufzeit, GPU-Bindung an vfio-pci, NIC-Hänger, Weboberfläche; dazu den Negativtest aus einer GPU-VM. Ausgabe OK/FEHLER je Prüfung, Exit 1 bei Fehlern.

Wann laufen lassen:

  1. Nach jedem Playbook-Lauf gegen die Knoten (site.yml, cluster.yml) und nach jedem Neustart (Abschnitt 6, Schritt 5).
  2. Vor einer Änderung an Firewall, Benutzern oder Netzwerk als Vergleichsbasis.
  3. Wöchentlich als Routine; Grafana (Abschnitt 7) deckt den Rest kontinuierlich ab.

Manuelle Ergänzungen, die das Skript nicht abdeckt: Anmeldung mit r.rapp@pve und TOTP in der Weboberfläche, Testmail (Abschnitt 9), Dock-Test an pve61 (Task 1.3, vor Ort), Wartungsmodus-Probe (Abschnitt 6).