Files
2026-08-04 20:52:55 +02:00

251 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Betrieb mit mehreren Ollama-Instanzen
Der Agent kann bis zu 64 voneinander unabhängige Ollama-Server als gemeinsamen Inferenz-Pool verwenden. Jeder Node lädt das vollständige Chat- und sofern für RAG erforderlich Embedding-Modell lokal. Der Pool erhöht damit den **Gesamtdurchsatz und die Ausfallsicherheit**; er teilt ein einzelnes Modell nicht über mehrere Rechner auf.
## Architektur
```text
GLPI AI Agent
Queue / Worker / Policies
|
v
Ollama Pool Router
| | |
Node 1 Node 2 Node 3
```
Jeder logische KI-Lauf Kategorie, Priorität, Status, Antwort oder Eskalation wird einem verfügbaren Node zugewiesen. Bei retryfähigen Netzwerk- oder Serverfehlern kann derselbe Request auf einem anderen kompatiblen Node wiederholt werden.
## Voraussetzungen je Node
Auf allen Nodes sollten installiert sein:
```text
Chat-Modell: OLLAMA_MODEL
Embedding-Modell: OLLAMA_EMBEDDING_MODEL
```
Bei `OLLAMA_REQUIRE_SAME_MODEL_DIGEST=true` prüft der Agent über `/api/tags`, dass alle erreichbaren Nodes exakt dieselben Modelldigests melden. Schon ein abweichender Digest macht den gesamten divergierenden Pool fail-closed, damit identische Tickets nicht aufgrund verschiedener Modellstände unterschiedlich bewertet werden.
Für Lenovo-Systeme mit integrierter Radeon-Grafik und gemeinsamem RAM ist als Ausgangspunkt sinnvoll:
```env
OLLAMA_NODE_MAX_INFLIGHT=1
OLLAMA_ROUTING_MODE=least_inflight
OLLAMA_KEEP_ALIVE=10m
OLLAMA_THINK=false
```
Der Gesamtdurchsatz wird zusätzlich durch `WORKERS` begrenzt. Mit drei Nodes und `WORKERS=2` können höchstens zwei Ticketpipelines gleichzeitig Inferenz anfordern. Für einen Lasttest mit drei gleichartigen Nodes ist daher beispielsweise sinnvoll:
```env
WORKERS=3
OLLAMA_NODE_MAX_INFLIGHT=1
```
Die Analysestufen eines einzelnen Tickets bleiben aus fachlichen Gründen weitgehend geordnet. Der größte Poolnutzen entsteht deshalb bei mehreren gleichzeitig wartenden Tickets oder Eskalationsläufen.
## Minimale Pool-Konfiguration
```env
OLLAMA_URLS=http://10.20.30.21:11434,http://10.20.30.22:11434,http://10.20.30.23:11434
OLLAMA_NODE_NAMES=lenovo-01,lenovo-02,lenovo-03
OLLAMA_ROUTING_MODE=least_inflight
OLLAMA_NODE_MAX_INFLIGHT=1
OLLAMA_FAILOVER_ENABLED=true
OLLAMA_FAILOVER_ATTEMPTS=0
OLLAMA_REQUIRE_SAME_MODEL_DIGEST=true
OLLAMA_REQUIRE_EMBEDDING_MODEL=true
```
`OLLAMA_FAILOVER_ATTEMPTS=0` bedeutet: maximal alle konfigurierten Nodes versuchen.
## Routing-Modi
### `least_inflight`
Empfohlener Standard. Der Node mit den wenigsten laufenden Requests wird bevorzugt. Bei gleicher Auslastung wird zunächst der bislang seltener verwendete Node gewählt; anschließend dienen mittlere Laufzeit und Name als stabile Tie-Breaker. Dadurch verteilt sich auch serieller Verkehr über gleichartige Nodes.
```env
OLLAMA_ROUTING_MODE=least_inflight
```
### `round_robin`
Requests werden zyklisch verteilt. Dieser Modus ist einfach, berücksichtigt aber Leistungsunterschiede nur begrenzt.
```env
OLLAMA_ROUTING_MODE=round_robin
```
### `weighted`
Geeignet für gemischte Hardware. Die Gewichte stehen positionsgleich zu `OLLAMA_URLS`.
```env
OLLAMA_URLS=http://lenovo-1:11434,http://lenovo-2:11434,http://gpu-server:11434
OLLAMA_NODE_NAMES=lenovo-1,lenovo-2,gpu-server
OLLAMA_NODE_WEIGHTS=1,1,6
OLLAMA_ROUTING_MODE=weighted
```
### `fastest_recent`
Bevorzugt Nodes mit der niedrigsten gleitenden mittleren Request-Laufzeit. Neue oder zurückgekehrte Nodes ohne Messwert werden zunächst einmal vermessen, damit sie nicht dauerhaft verhungern.
```env
OLLAMA_ROUTING_MODE=fastest_recent
```
## Startverhalten und Docker Compose
Der Webserver startet unabhängig vom Pool. Vor Knowledge-Initialisierung und Ticketverarbeitung wartet der Agent wiederholt auf mindestens einen gesunden, kompatiblen Ollama-Node. Ein noch bootender Node führt dadurch nicht mehr zu einem einmaligen dauerhaften Knowledge-Fehler; im Dashboard bleibt der Zustand währenddessen sichtbar.
Die Compose-Dateien besitzen keine harte Abhängigkeit des Agenten vom mitgelieferten `ollama`-Service mehr. Für ausschließlich externe Nodes kann gezielt nur der Agent gestartet werden:
```bash
docker compose up -d agent
```
`OLLAMA_URLS` hat Vorrang vor dem weiterhin aus Kompatibilitätsgründen gesetzten `OLLAMA_URL=http://ollama:11434`. Bei `docker compose up -d` ohne Servicenamen wird der gebündelte lokale Ollama-Service weiterhin mitgestartet, aber nur verwendet, wenn seine URL im effektiven Pool steht.
## Healthchecks und Cooldown
```env
OLLAMA_NODE_HEALTH_INTERVAL=15s
OLLAMA_NODE_FAILURE_COOLDOWN=30s
OLLAMA_NODE_REQUEST_TIMEOUT=10m
```
Der Healthcheck ruft `/api/tags` auf und prüft:
- HTTP-Erreichbarkeit,
- Vorhandensein des Chat-Modells,
- Vorhandensein des Embedding-Modells,
- Modelldigests,
- Kompatibilität mit den übrigen Nodes.
Ein retryfähiger Fehler setzt den betroffenen Node in einen Cooldown. Währenddessen erhält er keine neuen Requests. Ein späterer erfolgreicher Healthcheck macht ihn wieder sichtbar; der Cooldown läuft dennoch bis zu seinem Ende, um Flapping zu dämpfen.
## Failover
Failover wird ausgelöst bei:
- Verbindungsfehlern,
- Zeitüberschreitungen,
- HTTP 408,
- HTTP 429,
- HTTP 5xx,
- ungültigem äußerem Ollama-Response-JSON.
```env
OLLAMA_FAILOVER_ENABLED=true
OLLAMA_FAILOVER_ATTEMPTS=0
```
Nicht retryfähige 4xx-Fehler werden nicht auf andere Nodes gespiegelt. Die Modellaufrufe sind rein lesende Inferenzaufrufe; GLPI-Schreibaktionen erfolgen erst später durch die deterministische Go-Policy.
## Analyse-Diagnose
Jeder `AnalysisRun` speichert unter `provider`:
```json
{
"provider": "ollama-pool",
"routing_mode": "least_inflight",
"selected_node": "lenovo-02",
"selected_url": "http://10.20.30.22:11434",
"failover_used": true,
"attempt_count": 2,
"attempts": [
{
"attempt": 1,
"stage": "priority",
"node_name": "lenovo-01",
"outcome": "error",
"retryable": true
},
{
"attempt": 2,
"stage": "priority",
"node_name": "lenovo-02",
"outcome": "success"
}
]
}
```
Zusätzlich werden sofern Ollama sie liefert Ladezeit, Prompt-Tokens, Generierungstokens und zugehörige Laufzeiten gespeichert.
## Dashboard und Prometheus
`/api/status` enthält unter anderem:
```text
ollama_nodes
ollama_node_count
ollama_healthy_nodes
ollama_available_nodes
ollama_routing_mode
```
Prometheus exportiert pro Node:
```text
glpi_agent_ollama_node_healthy
glpi_agent_ollama_node_available
glpi_agent_ollama_node_inflight
glpi_agent_ollama_node_requests_total
glpi_agent_ollama_node_failures_total
glpi_agent_ollama_node_average_duration_ms
```
## Netzwerksicherheit
Ollama besitzt an seiner lokalen API üblicherweise keine eigene Mandantenauthentifizierung. Die Nodes sollten daher:
- in einem eigenen Server-/KI-Netz liegen,
- Port 11434 nur vom GLPI-AI-Agent-Host akzeptieren,
- nicht aus Benutzer-VLANs erreichbar sein,
- niemals direkt aus dem Internet erreichbar sein,
- bei standortübergreifender Nutzung über VPN oder einen TLS-Reverse-Proxy mit Netzwerk-/IP-Allowlist angebunden werden.
Beispiel auf jedem Node:
```env
OLLAMA_HOST=0.0.0.0:11434
```
Diese Freigabe allein ist nicht ausreichend; eine Host- oder Netzfirewall muss den Zugriff auf die Agent-IP begrenzen.
## Rollout-Empfehlung
1. Auf allen Nodes identische Ollama- und Modellstände installieren.
2. Chat- und Embedding-Modell einmal lokal laden.
3. Jeden Node einzeln mit `/api/tags` prüfen.
4. Pool zunächst mit `OLLAMA_REQUIRE_SAME_MODEL_DIGEST=true` starten.
5. Im Dashboard kontrollieren, dass alle Nodes `healthy=true` und `compatible=true` melden.
6. `OLLAMA_NODE_MAX_INFLIGHT=1` beibehalten und mehrere Testtickets parallel analysieren.
7. Erst nach Messung von RAM, Temperatur und Laufzeiten höhere Parallelität testen.
## Modellupdates bei strikter Digest-Prüfung
Bei `OLLAMA_REQUIRE_SAME_MODEL_DIGEST=true` ist ein gemischter Modellstand absichtlich nicht verfügbar. Ein Pull oder Austausch nur auf einem einzelnen aktiven Node kann den Pool deshalb beim nächsten Healthcheck fail-closed setzen. Sichere Varianten sind:
1. Agent in ein Wartungsfenster nehmen und das Modell auf allen Nodes aktualisieren.
2. Einen neuen, eindeutig versionierten Modelltag zunächst auf allen Nodes bereitstellen und erst danach `OLLAMA_MODEL` zentral umstellen.
3. Für Hardwarewartung einen Node aus `OLLAMA_URLS` entfernen, Agent neu starten und ihn erst mit passendem Digest wieder aufnehmen.
`OLLAMA_REQUIRE_SAME_MODEL_DIGEST=false` sollte nicht als normale Rolling-Update-Strategie verwendet werden, weil dann identische Tickets während der Übergangszeit von unterschiedlichen Modellständen bewertet werden können.
## Rückfall auf einen Einzelnode
Die bisherige Konfiguration bleibt kompatibel:
```env
OLLAMA_URL=http://localhost:11434
OLLAMA_URLS=
```
Ist `OLLAMA_URLS` leer, wird automatisch `OLLAMA_URL` als einzelner Pool-Node verwendet.