diff --git a/docs/BETRIEB.md b/docs/BETRIEB.md index b98d79b..3de9951 100644 --- a/docs/BETRIEB.md +++ b/docs/BETRIEB.md @@ -211,3 +211,23 @@ Wann laufen lassen: 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). + +## 14. Kubernetes (k3s) und Portainer (D6, seit 15.10.2026) + +Die GPU-VMs bilden mit der Dienst-VM `k3s` einen k3s-Cluster (v1.36.5+k3s1). Steuerung auf `k3s` (VM 110 auf pve48, tank, HA mit Replikation nach pve52 und pve44, 2 Kerne, 3 GB), Agents `gpu-pve44/46/48/52`. Docker bleibt in den VMs für noch nicht umgezogene Compose-Stacks (llama.cpp auf pve48, Exporter). + +| Was | Wo | +|---|---| +| Server-Adresse | per DHCP (heute 192.168.100.124, MAC `bc:24:11:a5:d5:52`); Agents nutzen den Namen `k3s.knaster` aus `/etc/hosts` (Rolle k3s-agent). Ändert sich die Adresse: `refresh-vm-access.sh`, dann `playbooks/k3s.yml` | +| Token und kubeconfig | nur auf ops: `/root/.config/knaster/k3s.env`, `/root/.kube/config`; `kubectl` liegt auf ops | +| Manifeste | `deploy/k8s/` (RuntimeClass `nvidia`, NVIDIA Device Plugin v0.20.1, Portainer Agent 2.45.2, `nex-speech/`) | +| Playbooks | `playbooks/k3s.yml` (Server, Agents, Grundausstattung), `playbooks/nex-speech-k3s.yml` (Umzug der Sprachdienste) | +| GPU in Pods | `runtimeClassName: nvidia` + `resources.limits: {nvidia.com/gpu: 1}`; Knoten-Labels `knaster.gpu=true`, `knaster.gpu.m4000=1`, `knaster.gpu.p2000=1` | +| Portainer | Umgebung „Kubernetes → Agent“ mit Adresse `:30778`, z. B. `192.168.100.124:30778` (Agent-Pod läuft im Namespace `portainer`) | + +- **Prüfen:** auf ops `kubectl get nodes` (fünf Knoten Ready), `kubectl get pods -A`, `kubectl -n nex get pods` (nex-stt, nex-tts auf gpu-pve52). +- **NEX-Sprachdienste** laufen seit 15.10. als Deployments im Namespace `nex` mit Host-Netz, Ports 8178/8179 auf der VM-Adresse wie zuvor; ufw der VM gilt weiter (nur appsrv08). Umzugstest 15.10.: TTS → STT Rundlauf liefert den Text exakt, M4000 belegt, Compose-Stack ist angehalten (Rückweg: `kubectl -n nex delete deploy nex-stt nex-tts`, dann in der VM `docker compose -f /opt/nex-speech/docker-compose.yml start`). `playbooks/nex-speech.yml` bricht deshalb ab, außer mit `-e nex_speech_compose=true`. +- **Images** aus Compose-Builds landen per `docker save | k3s ctr images import -` im containerd von k3s (Rolle nex-speech-k3s); kein Registry nötig. Für neue Dienste ohne Build reicht `image:` aus Docker Hub oder nvcr.io. +- **ufw in den VMs:** die Rolle k3s-agent erlaubt 10250/tcp, 8472/udp, 30000–32767/tcp aus dem LAN und alles aus dem Pod-Netz 10.42.0.0/16. +- **Aktualisieren:** `k3s_version` in `roles/k3s-server/defaults` und `roles/k3s-agent/defaults` anheben, `playbooks/k3s.yml`; erst Server, dann Agents (so läuft das Playbook). Kubernetes-Versionen immer nur eine Minor-Stufe je Schritt. +- **Stromausfall:** VM 110 startet automatisch (onboot, HA). Agents verbinden sich neu, Pods starten mit den Knoten. Sollte `k3s` auf einen anderen Knoten umziehen, bleibt die Adresse (gleiche MAC), sobald die DHCP-Reservierung am DC steht. diff --git a/docs/superpowers/plans/2026-10-12-aufbau-cluster-knaster.md b/docs/superpowers/plans/2026-10-12-aufbau-cluster-knaster.md index f61b7c7..bfec2b9 100644 --- a/docs/superpowers/plans/2026-10-12-aufbau-cluster-knaster.md +++ b/docs/superpowers/plans/2026-10-12-aufbau-cluster-knaster.md @@ -73,6 +73,7 @@ Außerhalb des Clusters: | **D2** | GPU als VM oder LXC | **Pro GPU-Knoten eine Ubuntu-24.04-VM mit allen Karten des Knotens**, darin Docker Compose pro Rolle. | Der Host-Kernel (7.0) bleibt ohne NVIDIA, Proxmox-Updates gefährden den Treiber nicht. R580 kommt als Ubuntu-Paket und ist per Snapshot rückrollbar. IOMMU-Gruppen sind geprüft. Eine VM pro Knoten statt pro Rolle (ADR-0001) spart RAM. Das Argument „gemischte Generationen“ aus ADR-0001 gilt im Cluster nicht mehr, alle Karten sind Maxwell/Pascal. Kosten: 2–5 % CPU, fest reservierter VM-RAM (12–16 GB von 32 GB). | LXC mit Host-Treiber: braucht R580 auf Kernel 7.0 oder einen festgehaltenen älteren Kernel. | | **D3** | Ada-Rechner | **Windows bleibt.** `LocalLLMWorker.ps1` mit llama-server (CUDA) meldet sich über die Worker-Registry v2. Die knaster-Slots `tier1-general`/`tier1-flex` lösen auf einen Worker auf, der online ist, sonst tier0. | Die Registry v2 ist fast fertig (44 von 55 Schritten). Mitarbeitende werden nicht gestört. vLLM läuft unter Windows nicht nativ, Multi-LoRA, QLoRA und Qwen3-TTS kommen deshalb erst mit einer späteren WSL2-Entscheidung (Phase 9). | Dual-Boot mit Proxmox: scheidet aus, die Rechner werden tagsüber genutzt. | | **D4** | LiteLLM | **Kein eigener LiteLLM im knaster-Infra.** Der Router nutzt den LiteLLM auf appsrv08 (mit PSE), die lokalen Slots werden dort als Modelle eingetragen. | Es läuft bereits ein dritter LiteLLM; noch einer würde PSE für tier0 umgehen. Ein Modellwechsel bleibt eine Datenänderung. | Eigener LiteLLM nur für lokale Slots, ohne OpenRouter-Zugang. | +| **D6** | Orchestrierung der Gäste-Dienste | **k3s** (Server auf Dienst-VM `k3s`, Agents = GPU-VMs, NVIDIA Device Plugin), Portainer auf appsrv08 als Oberfläche über den Portainer-Agent (NodePort 30778). Entschieden 15.10.2026. | Nutzer will die vier GPU-Hosts in Portainer als einen Cluster sehen. Portainer kennt dafür nur Swarm oder Kubernetes; Kubernetes plant GPUs sauber (Device-Plugin), Ökosystem (Helm) größer. GPU-Rechenleistung identisch, Grundlast k3s ~0,5–1 GB je Knoten. | Docker Swarm (kaum GPU-Planung, kein Helm), RKE2 (gleiches Haus, schwerer), kubeadm. | | **D5** | IP-Plan | **Knoten behalten .207–.214.** Gäste bekommen einen festen Block außerhalb des DHCP-Bereichs. Vorschlag `.220–.239`, wird in Task 0.3 gegen den DHCP-Bereich geprüft. | Die STT-Konfiguration braucht IP-Literale. Die alten GODEL-DNS-Einträge zeigen, dass die Knoten-IPs aus DHCP stammen, deshalb Reservierungen anlegen. | VLAN `svc` (PLAN §1.4) später, wenn der Switch das zulässt. | ## Was hängt woran (Stand 12.10.) @@ -129,7 +130,7 @@ Ersetzt PLAN §8 „0 Fundament“ (Teil Inventar) und IMPLEMENTATION „Gemeins **Wo:** remote (DHCP-Server, vermutlich DC `.120` oder UniFi) · **Planner:** „PVE-Config: Netzwerk prüfen – Bridge, VLAN-Fähigkeit und NIC-Kompatibilität“ - [x] (14.10.) ops und infra auf feste Adressen .173/.188 umgestellt (BETRIEB §10), damit hängt der Steuerrechner nicht mehr am Lease. Laptop kam am 14.10. per Dock mit .181, als zweite Adresse in `firewall.management` aufgenommen. -- [ ] Reservierungen beim DC-Support anfordern (MAC-Liste vom 14.10.: Knoten, ops bc:24:11:c1:d9:c8, infra bc:24:11:6d:e5:c0, gpu-pve52 bc:24:11:92:4b:eb, Laptop WLAN 34:fd:70:65:06:6c und Dock 84:ba:59:fb:e0:36) plus Ausschluss `.220–.239`. Nötig ist dafür nur die Gruppe „DHCP-Administratoren“ auf dem DC .120, kein Domänen-Admin. +- [ ] Reservierungen beim DC-Support anfordern (15.10. angefragt; MAC-Liste vom 14.10.: Knoten, ops bc:24:11:c1:d9:c8, infra bc:24:11:6d:e5:c0, gpu-pve52 bc:24:11:92:4b:eb, **nachreichen: k3s-VM bc:24:11:a5:d5:52 → .124**, Laptop WLAN 34:fd:70:65:06:6c und Dock 84:ba:59:fb:e0:36) plus Ausschluss `.220–.239`. Nötig ist dafür nur die Gruppe „DHCP-Administratoren“ auf dem DC .120, kein Domänen-Admin. - [ ] Später (Phase 9): eigenes Verwaltungs-/Dienstnetz als VLAN, Vorbedingung: Switch kann VLAN, Routing beim Netzverantwortlichen geklärt. Bis dahin bleibt die Adressliste in der Proxmox-Firewall der Schutz. - [ ] DHCP-Bereich auslesen. **Seit 13.10. dringender:** Die Firewall (4.4) lässt nur .151 (Laptop), .173 (ops) und .188 (infra) an die Verwaltungsports; ein Lease-Wechsel sperrt die Quelle aus (BETRIEB §10). Für .207, .209, .210, .212 und .214 Reservierungen auf die MACs der Knoten anlegen (MACs stehen im Healthcheck). Ebenso eine Reservierung für den Admin-Laptop (heute .151 per WLAN). Die Firewall in 4.4 lässt nur diese Adresse zu, ein Lease-Wechsel würde sonst aussperren. - [ ] Gäste-Block festlegen (Vorschlag `.220–.239`) und als Ausschluss im DHCP eintragen. @@ -355,7 +356,9 @@ Ersetzt GPU-Knoten 3 (Teil Cluster). Mit 5 Stimmen ist **kein QDevice** nötig. Ersetzt PLAN §8 „1 Data Plane“. -- [ ] **6.1 GPU-Rollen:** `deploy/compose/gpu-llamacpp` in den GPU-VMs nach der Zuordnung aus Task 3.3, also Embedding und Rerank redundant auf zwei Knoten, Chat für verifier und signature. Prüfung: Canary-Checks grün (`knaster` Canary-Prober). +- [x] (15.10.) **6.0 k3s (D6):** Dienst-VM `k3s` (tofu `service_vms`, HA + Replikation über Rolle pve-host), Rollen `k3s-server`, `k3s-agent`, `k3s-apps`, Manifeste `deploy/k8s/`, `playbooks/k3s.yml`. Fünf Knoten Ready, `nvidia.com/gpu` 2/2/2/1, Portainer-Agent läuft (NodePort 30778 von Laptop erreichbar). Umzugstest: NEX-Sprachdienste als Deployments (`playbooks/nex-speech-k3s.yml`), Rundlauf TTS→STT korrekt. BETRIEB §14. + - [ ] Offen: Umgebung in Portainer (appsrv08) anlegen (Nutzer), DHCP-Reservierung für VM 110 (`bc:24:11:a5:d5:52`), llama.cpp (6.1) direkt als k3s-Manifeste statt Compose, Monitoring der Pods (kube-state-metrics / Prometheus-Scrape über k3s), Exporter-Stacks umziehen, Docker danach aus den VMs entfernen. +- [ ] **6.1 GPU-Rollen:** ab 15.10. als k3s-Manifeste (D6) statt Compose: `deploy/compose/gpu-llamacpp` in den GPU-VMs nach der Zuordnung aus Task 3.3, also Embedding und Rerank redundant auf zwei Knoten, Chat für verifier und signature. Prüfung: Canary-Checks grün (`knaster` Canary-Prober). - [ ] **6.2 STT und TTS für NEX** – Auftrag vom 12.10. mit Abgleich: `docs/auftraege/2026-10-12-sprachmodelle-nex.md` (Erkennung whisper.cpp auf einer M4000, naheliegend `gpu-pve52`; Ausgabe Piper auf CPU, Port 8179; Abnahme und Rückmeldeformat dort). Läuft nach Task 3.2, gern als Subagent. **Blockiert für die Abnahme:** feste IP (D5). Bisheriger Text (nex-STT-Plan Tasks 2–4): `whisper-server` als zusätzlicher Dienst in der GPU-VM des in Task 3.3 gewählten Knotens. Neuer Slot `stt-de` im Katalog. Port 8178 nur von `192.168.100.29` (Firewall der VM bzw. des Gasts). Prüfung: Von appsrv08 liefert `curl -F file=@probe.wav http://:8178/v1/audio/transcriptions` deutschen Text, von einem anderen Rechner wird der Zugriff abgelehnt. - [x] (12.10.) Umgesetzt in `gpu-pve52`: `nex-stt` (whisper.cpp v1.9.4, CUDA 12.6, sm_52/61, `large-v3-turbo`, Port 8178) und `nex-tts` (Piper 1.8.0, `de_DE-thorsten-high` + `de_DE-kerstin-low`, Port 8179) als `deploy/compose/nex-speech`, Rolle/Playbook `nex-speech`. ufw in der VM (8178/8179 nur von `.29`, SSH aus dem LAN), Proxmox-Firewall bewusst aus. - [x] (12.10.) Tests in der VM und von ops (temporäre Regel, danach entfernt): 10 s → 2,94 s, 60 s → 8,63 s (Median), TTS-TTFB 0,64–0,91 s (mp3/pcm/opus), Autostart nach `qm reboot 252` geprüft, keine Texte in Logs. Rückmeldung im Auftrag. diff --git a/platform/proxmox/ansible/playbooks/k3s.yml b/platform/proxmox/ansible/playbooks/k3s.yml index eae8353..6e2bc16 100644 --- a/platform/proxmox/ansible/playbooks/k3s.yml +++ b/platform/proxmox/ansible/playbooks/k3s.yml @@ -3,6 +3,17 @@ # ansible-playbook playbooks/k3s.yml - name: k3s-Server hosts: k3s_server + pre_tasks: + - name: DHCP-Client-ID auf MAC umstellen (Reservierung am DC, wie bei den GPU-VMs) + ansible.builtin.copy: + dest: /etc/netplan/99-knaster-dhcp-id.yaml + content: | + network: + version: 2 + ethernets: + eth0: + dhcp-identifier: mac + mode: "0600" roles: [k3s-server] - name: k3s-Agents (GPU-VMs) diff --git a/platform/proxmox/ansible/playbooks/nex-speech.yml b/platform/proxmox/ansible/playbooks/nex-speech.yml index 5e7dd3a..72a83df 100644 --- a/platform/proxmox/ansible/playbooks/nex-speech.yml +++ b/platform/proxmox/ansible/playbooks/nex-speech.yml @@ -1,6 +1,13 @@ # NEX-Sprachdienste (Task 6.2): Erkennung (whisper.cpp, M4000) und Ausgabe (Piper, CPU) in gpu-pve52. # Aufruf auf ops: ansible-playbook playbooks/nex-speech.yml # Vorher Zugang auffrischen (DHCP): bash ../scripts/refresh-vm-access.sh -- name: NEX-Sprachdienste +# Seit 15.10.2026 laufen die Dienste in k3s (playbooks/nex-speech-k3s.yml, D6). Dieses Playbook würde +# den Compose-Stack wieder starten und die Host-Ports 8178/8179 belegen. Nur mit -e nex_speech_compose=true. +- name: NEX-Sprachdienste (Docker Compose, abgelöst) hosts: "{{ nex_speech_hosts | default('gpu-pve52') }}" + pre_tasks: + - name: Abgelöst durch k3s + ansible.builtin.fail: + msg: "Die NEX-Sprachdienste laufen in k3s (playbooks/nex-speech-k3s.yml). Compose nur mit -e nex_speech_compose=true." + when: not (nex_speech_compose | default(false) | bool) roles: [nex-speech]