7.5 KiB
7.5 KiB
Plan: NVIDIA-Windows-Rechner als flexibler Cluster hinter dem bestehenden Gateway
Context
Mehrere Windows-PCs mit NVIDIA-GPUs sollen zusätzliche Rechenleistung liefern. Der bestehende
Linux-PC (AMD, Docker: Caddy + llama-swap) bleibt der einzige Endpunkt (:8800, gleicher API-Key).
Jeder Knoten kann jedes Cluster-Modell ausführen und wechselt bei Bedarf (llama-swap). Linux ist
auf den Knoten nicht nötig: llama-swap (llama-swap_265_windows_amd64.zip) und llama.cpp
(llama-bXXXXX-bin-win-cuda-{12.4|13.4}-x64.zip + cudart-…) gibt es fertig für Windows.
Erkenntnisse aus der Recherche:
- llama-swap v265 leitet über
peerspro Modell an einen Server weiter (URL-Pfad wird angehängt). Das Load-Balancing übernimmt deshalb Caddy. - llama-swap löst
${env.VAR}in der Config auf, also kommen keine Secrets ins Git. - Ältere llama.cpp-Builds werden gelöscht (b11610 gibt es schon nicht mehr). Der Installer wählt den Build über die GitHub-API (
latestoder fest). - Caddy auf dem Host-Netz ist für den Container wegen ufw schwer erreichbar. Deshalb läuft der Loadbalancer als eigener Container im Compose-Netz.
Architektur
Client ─► Caddy :8800 (IP-Filter, API-Key) ─► llama-swap (AMD, lokal)
│ lokale Modelle wie bisher
└─ peers: cluster-<m> ─► http://cluster-lb:8090/m/cluster-<m>
cluster-lb (Caddy-Container, generiert):
/m/cluster-qwen3.5-35b-a3b/* ─► Knoten [A, B, C] (Stammknoten A)
/m/cluster-glm-4.7-flash/* ─► Knoten [B, C, A] (Stammknoten B)
/m/cluster-qwen3.5-9b/* ─► Knoten [C, A, B] (Stammknoten C)
Win-Knoten: llama-swap.exe :8080 mit ALLEN cluster-Modellen, API-Key, Firewall nur Gateway-IP
Routing ohne unnötige Modellwechsel: Für jedes Modell enthält der Pool alle Knoten, aber in rotierter Reihenfolge. Dazu kommen lb_policy first und unhealthy_request_count <Slots>:
- Eine Anfrage geht an den Stammknoten des Modells. Dort ist das Modell meist schon geladen und der Prompt-Cache noch vorhanden.
- Ist der Stammknoten belegt oder ausgefallen, geht sie an den nächsten Knoten. Der lädt das Modell dann, das ist der flexible Fall.
- Sind alle Knoten belegt, wartet Caddy (
lb_try_duration 5m,lb_try_interval 1s), bis einer frei wird. - Health-Checks auf
/healthalle 10 s, ausgefallene Knoten werden übersprungen. - Wenn es mehr Modelle als Knoten gibt, teilen sich Modelle einen Stammknoten (Zuordnung reihum).
Änderungen auf dem Gateway (Linux)
- docker-compose.yml: neuer Service
cluster-lb(caddy:${CADDY_TAG}), nur im Compose-Netz und ohne Port nach außen. Er mountetcaddy/cluster.Caddyfile.llama-swapbekommtCLUSTER_API_KEYals Umgebungsvariable. - Neu
scripts/cluster-gen.sh: liestCLUSTER_NODES="192.168.178.50:8080 192.168.178.51:8080 …"undCLUSTER_SLOTS(Standard 1) aus.env. Die Modellliste kommt auscluster/windows/node-config.yaml(einzige Quelle, Schlüsselcluster-*). Daraus erzeugt das Skriptcaddy/cluster.Caddyfile(in.gitignore), mit einemhandle_path /m/<modell>/*und rotierter Upstream-Liste pro Modell. Ohne Knoten entsteht eine gültige Datei, die 503 liefert. scripts/start.sh ruft das Skript vordocker compose upauf. - llama-swap/config.yaml: Block
peers:mit einem Eintrag pro Cluster-Modell,proxy: http://cluster-lb:8090/m/<modell>,apiKey: ${env.CLUSTER_API_KEY}, dazu großzügigetimeouts.responseHeaderfür Modellwechsel und Download. .env.example/.env:CLUSTER_API_KEY(start.sh erzeugt ihn wieLLM_API_KEY, wenn er fehlt),CLUSTER_NODES,CLUSTER_SLOTS.- Neu
scripts/cluster-status.sh: zeigt pro Knoten/health, das geladene Modell (/running) und die Antwortzeit. start.sh zeigt die Ausgabe im Statusblock, wenn Knoten gesetzt sind.
Windows-Knoten-Skripte (cluster/windows/)
install-node.ps1(als Admin; wiederholbar, dient auch zum Update): Parameter-GatewayIPund-ApiKey(Pflicht),-Port 8080,-InstallDir C:\localai-node,-LlamaBuild latest,-Cuda auto|12.4|13.4,-Preload <modell>(optional),-HfToken,-KeepSleep,-Force.- Prüft Admin-Rechte,
nvidia-smi(GPU, VRAM, Compute Capability, Treiber) und freien Speicherplatz (Warnung unter 60 GB, weil alle Modelle auf jedem Knoten liegen können). - CUDA-Variante: 13.4, wenn Compute Capability ≥ 7.5 und Treiber ≥ 580, sonst 12.4.
- Lädt llama-swap und llama.cpp CUDA + cudart herunter, entpackt sie nach
bin\und testetllama-server.exe --version. - Schreibt
config.yamlaus der Vorlage. Bestehende Dateien bleiben unangetastet, außer bei-Force. - Erzeugt
start-node.cmd: setztLLAMA_CACHE,HF_TOKENundNODE_API_KEY, startetllama-swap.exe -config … -listen 0.0.0.0:PORTund schreibt das Log nachlogs\. - Firewall-Regel: TCP-Port eingehend nur von
GatewayIP. - Geplante Aufgabe
LocalAI-Node: Start beim Booten, als SYSTEM, ohne Laufzeitlimit, Neustart bei Absturz. - Standby am Netzteil aus (
powercfg), außer bei-KeepSleep. - Startet die Aufgabe, wartet auf
/healthund gibt die Zeile fürCLUSTER_NODESaus.
- Prüft Admin-Rechte,
download-models.ps1(optional): lädt alle Cluster-Modelle vorab herunter, indem es jedes Modell einmal kurz anfragt. So dauert die erste echte Anfrage nicht wegen eines 20-GB-Downloads.node-config.yaml(Vorlage, Quelle der Modellliste): alle Cluster-Chat-Modelle (cluster-qwen3.5-35b-a3b,cluster-glm-4.7-flash,cluster-qwen3.5-9b) in einer Swap-Gruppe, Pfade mit/,--fitmit--fit-target 1024(passt sich automatisch an den VRAM des Knotens an),-np <Slots>. DazuapiKeys: ["${env.NODE_API_KEY}"], optional Preload,healthCheckTimeout: 3600.install-node.cmd: Doppelklick-Wrapper, fordert Admin-Rechte an, setzt-ExecutionPolicy Bypassund fragt Gateway-IP und Key ab.status-node.ps1: Zustand der Aufgabe,/health,/running,nvidia-smi, letzte Logzeilen.uninstall-node.ps1: entfernt Aufgabe und Firewall-Regel und löscht optional das Verzeichnis (-KeepModels).
Doku
- Neu
docs/cluster.md: Architektur und Routing (Stammknoten, Überlauf), Ablauf (Key → Knoten installieren → IP inCLUSTER_NODES→./scripts/start.sh), Modell hinzufügen (nur innode-config.yaml+peers, dann Knoten mit-Forceaktualisieren). Grenzen: Ein Modell, das größer als VRAM+RAM eines Knotens ist, wird nicht über mehrere PCs verteilt. Kleine GPUs lagern per--fitin den RAM aus und sind dann langsamer. - README.md: Abschnitt „Cluster“ mit Link, Dateiliste ergänzen. Die Client-Doku nennt die
cluster-*-Modellnamen.
Verifikation
cluster-gen.shmit 0, 1 und 3 Test-Knoten ausführen und jeweilscaddy validate(Docker,caddy:2.10.2-alpine) laufen lassen. Außerdemdocker compose config.- Kette ohne Windows testen: Als Fake-Knoten dient eine zweite llama-swap-Linux-Binary bzw. ein Echo-Server im Scratchpad, auf zwei Ports. Prüfen:
/v1/modelszeigtcluster-*.- Die Anfrage läuft über :8800 → peer → cluster-lb → Stammknoten.
- Streaming funktioniert.
- Bei belegtem Stammknoten geht die Anfrage an den nächsten Knoten.
- Ein gestoppter Knoten wird übersprungen.
- PowerShell-Syntax mit
pwshparsen, falls verfügbar. Den echten Lauf auf einem Windows-PC macht der Nutzer; der Installer endet mit einem Selbsttest (/health). - Der bestehende Betrieb bleibt unverändert:
./scripts/start.shstartet weiter erfolgreich, auch ohne Knoten.