Architektur¶
Die Architektur folgt einem Drei-Schichten-Modell: eine Verwaltungsschicht (Python-Anwendung mit Web-UI), eine Container-Orchestrierungsschicht (Docker-API, gemeinsames Bridge-Netzwerk) und eine Inference-Schicht (vLLM-Container pro Modell). Sämtliche dauerhaften Komponenten — Reverse-Proxy, API-Proxy, Datenbank, Monitoring — laufen als Docker-Container im selben Bridge-Netzwerk und werden von der Verwaltungsschicht über die Docker-API gesteuert. Die Verwaltungsschicht selbst läuft auf dem Host außerhalb des Container-Netzwerks; Anfragen zur Inference fließen ausschließlich über den Reverse-Proxy.
Auf einen Blick¶
- Single-File-Verwaltungsanwendung in Python mit Gradio-UI; Bindung ausschließlich auf
127.0.0.1:7860. Die Oberfläche wird in zwei Sprachinstanzen bereitgestellt (Deutsch unter/de, Englisch unter/en; Umschalter in der Kopfzeile, Weiterleitung von/nach Browser-Sprache). - Docker-Bridge-Netzwerk
llm-networkals gemeinsame Kommunikationsebene aller Container, mit Docker-internem DNS. - Caddy als zentraler HTTPS-Reverse-Proxy für externe Zugriffe; alle anderen Container ohne Host-Port-Mapping.
- LiteLLM-Proxy als OpenAI-kompatibler Vermittler für Chat, Vision und Embedding; Direktrouten an vLLM-Container für Speech-to-Text, Text-to-Speech und Bildgenerierung.
- PostgreSQL für Virtual Keys, ohne Port-Exposition und ausschließlich im Docker-Netzwerk erreichbar.
- Optionaler Monitoring-Stack aus Prometheus, Grafana und NVIDIA DCGM Exporter.
- Eine zentrale JSON-Datei hält den gesamten Zustand; alle weiteren Konfigurationsdateien werden aus ihr generiert.
Architekturbeschreibung¶
Die Verwaltungsanwendung läuft als systemd-Dienst auf dem Host und kommuniziert über den Docker-Unix-Socket mit dem Docker-Daemon. Sie ist die einzige Komponente außerhalb des Container-Netzwerks und hält den globalen Zustand: erkannte GPUs, MIG-Konfiguration, registrierte Modelle, API-Schlüssel, Image-Versionen (global und je Modell) und HTTPS-Einstellungen. Aus diesem Zustand werden bei Änderungen die Konfigurationsdateien für LiteLLM, Caddy, Prometheus und Grafana neu erzeugt; betroffene Container werden anschließend neu gestartet oder neu geladen.
Komponenten und Datenfluss¶
flowchart TB
Client[Client / Browser / API]
subgraph Host[Host-System]
Manager[LLM-Manager<br/>Gradio Web-UI<br/>127.0.0.1:7860]
NVSMI[nvidia-smi]
Config[(config.json)]
HFCache[(Hugging Face Cache)]
subgraph DockerNet[Docker-Netzwerk llm-network]
Caddy[Caddy<br/>HTTPS Reverse Proxy<br/>:443]
LiteLLM[LiteLLM Proxy<br/>:4000]
Postgres[(PostgreSQL<br/>Virtual Keys)]
subgraph vLLMs[vLLM-Container pro Modell]
vLLM1[Chat / Vision / Embedding]
vLLM2[Speech-to-Text]
vLLM3[Text-to-Speech / Bildgenerierung]
end
subgraph Monitoring[Monitoring optional]
Prom[Prometheus]
Grafana[Grafana]
DCGM[DCGM Exporter]
end
end
end
Client -->|HTTPS| Caddy
Manager -->|Docker API| Caddy
Manager -->|Docker API| LiteLLM
Manager -->|Docker API| vLLMs
Manager -->|nvidia-smi| NVSMI
Manager <--> Config
Caddy -->|"/v1/*"| LiteLLM
Caddy -->|"/models/{name}/*"| vLLM2
Caddy -->|"/models/{name}/*"| vLLM3
Caddy -->|"/open/{name}/*"| LiteLLM
Caddy -->|"/grafana/*"| Grafana
LiteLLM --> vLLM1
LiteLLM --> Postgres
vLLM1 -.-> HFCache
vLLM2 -.-> HFCache
vLLM3 -.-> HFCache
Prom --> vLLM1
Prom --> vLLM2
Prom --> vLLM3
Prom --> LiteLLM
Prom --> DCGM
Grafana --> Prom
Erläuterung des Diagramms¶
Eingehende Anfragen treffen ausschließlich auf Caddy. Caddy unterscheidet drei Routing-Pfade: Anfragen unter /v1/* werden an LiteLLM weitergereicht; LiteLLM authentifiziert über den Master-Key oder einen Virtual Key (gegen PostgreSQL) und leitet die Anfrage an den passenden vLLM-Container weiter, bei mehreren Replicas eines Modells nach least-busy-Strategie. Anfragen unter /models/<n>/v1/* werden direkt an den genannten vLLM-Container weitergereicht; Caddy entfernt das Präfix und prüft den Authorization-Header per Expression-Matcher gegen den Master-Key und alle eingetragenen Direkt-Routen-Keys. Anfragen unter /open/<n>/v1/* (sofern aktiviert) lassen jeden nicht-leeren Bearer-Token passieren, ersetzen ihn durch den Master-Key und reichen die Anfrage an LiteLLM weiter.
Die Verwaltungsanwendung selbst ist nicht im Datenfluss der Inference-Anfragen beteiligt. Sie liest GPU-Informationen über nvidia-smi, steuert den Container-Lebenszyklus über die Docker-API, kommuniziert mit der LiteLLM-Management-API zur Schlüsselerzeugung und schreibt sämtliche Konfigurationsdateien aus dem zentralen JSON-Zustand. Der Hugging-Face-Cache ist ein gemeinsames Volume, das in alle vLLM-Container eingebunden wird, sodass Modelldateien nur einmal vorgehalten werden.
Container-Layout¶
Alle Container laufen im Bridge-Netzwerk llm-network und kommunizieren über Docker-internes DNS. Nur Caddy (Port 443 und 80) und das Web-UI (Port 7860, ausschließlich 127.0.0.1) sind auf dem Host erreichbar; PostgreSQL, LiteLLM, alle vLLM-Container und der Monitoring-Stack sind ohne Host-Port-Mapping konfiguriert. Container werden mit Labels versehen (managed-by, model-name, model-type), sodass sich von der Verwaltungsanwendung gepflegte Container von anderen unterscheiden lassen.
Die Image-Auswahl pro Modell folgt einer festen Priorität: ein optionaler Modell-Override schlägt zuerst zu; andernfalls bestimmt der Modell-Typ die Image-Familie — Rezept-Image (etwa für Speech-to-Text mit Whisper- oder Audio-Abhängigkeiten), vLLM-Omni-Image (Text-to-Speech, Bildgenerierung) oder Standard-vLLM-Image (Chat, Vision, Embedding) — und eine optionale Per-Modell-Version den Versionsstand; fehlt sie, greift die global konfigurierte Version. So können Modelle unterschiedlicher vLLM-Linien dauerhaft nebeneinander betrieben werden. Image-Auflösung und Startkommando entstehen in gemeinsamen, seiteneffektfreien Hilfsfunktionen, die auch die Konsistenzprüfung verwendet — Soll- und Ist-Zustand stimmen dadurch strukturell überein. Rezept-Images werden auf Wunsch direkt aus der Oberfläche heraus gebaut und je Basisversion getrennt vorgehalten; die zugehörigen Pakete sind als Rezepte hinterlegt.
Schichten der Verwaltungsanwendung¶
Die Python-Anwendung ist intern in mehrere Schichten gegliedert:
- Hardware-Schicht — GPU-Discovery, NVLink- und MIG-Erkennung, MIG-Verwaltung und MIG-Persistenz.
- Datenmodell-Schicht — Modell- und Anwendungs-Konfiguration als typisierte Datenklassen mit Migrationspfaden für ältere Konfigurationen.
- Orchestrierungs-Schicht — Container-Lebenszyklus (Erstellen, Starten, Stoppen, Logs), Image-Auswahl, Image-Build-Logik für Rezept-Images sowie der Konsistenzabgleich zwischen Konfiguration und laufenden Containern.
- Konfigurations-Schicht — Persistenz und Generierung der LiteLLM-, Caddy- und Prometheus-Konfigurationen aus dem zentralen JSON-Zustand.
- Monitoring-Schicht — Energie-Sampling über
nvidia-smi, Sitzungs-Tracking und CSV-Export. - UI-Schicht — Gradio-Oberfläche mit tabbasierter Strukturierung, Echtzeit-Updates und Event-Handlern; zweisprachig (Deutsch/Englisch) über je eine App-Instanz pro Sprache, deren Texte aus einem eingebetteten Wörterbuch stammen.
Nebenläufigkeit und Robustheit¶
Sicherheitsrelevante Operationen sind so ausgelegt, dass sie das Gesamtsystem nicht in einen inkonsistenten Zustand bringen können. PostgreSQL-Container werden zwar gestoppt, aber niemals entfernt, und das zugehörige Volume wird niemals gelöscht. LiteLLM-Neustarts halten eine feste Wartezeit zwischen Stop und Start ein und berühren PostgreSQL und Caddy nicht. Beim ersten Start von PostgreSQL werden Datenbank-Migrationen durch einen Health-Check mit großzügiger Anlaufzeit abgesichert. Aufrufe externer Werkzeuge (nvidia-smi, Docker-CLI) laufen mit Zeitlimits und definierter Fehlerbehandlung, sodass ein nicht reagierender GPU-Treiber die Verwaltungsanwendung nicht blockiert. Aktualisierungen von Image-Versionen wirken selektiv: Nur Container, deren Ziel-Image sich ändert, werden neu gestartet.
Die Wiederherstellung nach einem Reboot läuft als fünfstufiger Vorgang: Wiederherstellung der MIG-Partitionen, Start von PostgreSQL, Start aller Modelle mit Status „running", Start von LiteLLM und schließlich Aktualisierung der Caddy-Konfiguration. Wenn der Monitoring-Stack aktiv ist, folgt er als sechster Schritt.
Konfiguration und Deployment¶
Die Anwendung wird als systemd-Dienst betrieben; ihre Konfiguration liegt in einem festen Verzeichnis auf dem Host, das über eine Umgebungsvariable überschreibbar ist. Aus der zentralen config.json werden bei jeder Änderung litellm-config.yaml, Caddyfile, prometheus.yml und Grafana-Provisioning-Dateien neu erzeugt. Sensible Daten — die config.json mit Schlüsseln und Datenbank-Passwort — werden mit eingeschränkten Dateirechten abgelegt. Die DATABASE_URL wird ausschließlich als Container-Umgebungsvariable übergeben und nicht in Konfigurationsdateien geschrieben.
Technologie-Übersicht¶
| Schicht | Komponente |
|---|---|
| Web-UI | Gradio |
| Programmiersprache | Python |
| Container-Orchestrierung | Docker, Docker SDK für Python, NVIDIA Container Toolkit |
| Inference-Backends | vLLM, vLLM-Omni |
| API-Proxy | LiteLLM |
| HTTPS-Reverse-Proxy | Caddy |
| Datenbank | PostgreSQL |
| Monitoring | Prometheus, Grafana, NVIDIA DCGM Exporter |
| Modell-Bezug | Hugging Face Hub (Hugging-Face-CLI) |
| Konfigurationsformate | JSON, YAML |
| Datenverarbeitung | pandas |
| Deployment | systemd, Docker Bridge Network |