Claude: Lens-Distortions
This commit is contained in:
420
doc/docker_containerization_roadmap.md
Normal file
420
doc/docker_containerization_roadmap.md
Normal file
@@ -0,0 +1,420 @@
|
||||
# Docker Containerization Roadmap
|
||||
|
||||
## Ziel
|
||||
|
||||
Die Blender-Rendering-Pipeline soll vollständig containerisiert und später in eine verteilte Job-Infrastruktur integriert werden.
|
||||
|
||||
Wichtige Randbedingungen:
|
||||
|
||||
* Blender-Container sollen nur laufen, wenn tatsächlich Renderaufträge vorhanden sind.
|
||||
* Verschiedene Jobtypen sollen unterschiedliche Container verwenden können.
|
||||
* Die Infrastruktur soll zukünftig nicht nur Blender-Rendering, sondern auch andere Workloads (AI-Training, STL-Verarbeitung, Datensatz-Generierung, Batch-Konvertierungen usw.) unterstützen.
|
||||
* Die Ausführung soll auf mehreren PCs/Worker-Nodes möglich sein.
|
||||
* Die bestehende Python-Logik soll möglichst unverändert bleiben.
|
||||
|
||||
---
|
||||
|
||||
# Review / Bewertung
|
||||
|
||||
**Gesamteinschätzung:** schlüssig und machbar. Die Zielarchitektur (Redis-Queue +
|
||||
Nomad-Scheduler, Container nur bei Bedarf, mehrere Workload-Typen, horizontale Skalierung)
|
||||
ist tragfähig und zukunftssicher. Es fehlen einige technische Punkte, die unten ergänzt sind.
|
||||
|
||||
## Wichtigste Korrektur: Renderer und Pipeline sind ZWEI Container, nicht einer
|
||||
|
||||
Phase 1 spricht von „Rendering-Pipeline **+** Analyse-Pipeline" in *einem* Container.
|
||||
Das sollte getrennt werden — die beiden haben grundverschiedene Profile:
|
||||
|
||||
| | Render-Container | Pipeline-Container |
|
||||
|---|---|---|
|
||||
| Image | `approbot/blender-renderer` | `approbot/pose-pipeline` |
|
||||
| Basis | Blender 4.5 + bpy + cv2 + numpy (~1–2 GB) | `python:3.11-slim` + numpy/scipy/opencv (~200 MB) |
|
||||
| GPU | ja (Cycles, CUDA/OPTIX) | nein |
|
||||
| Zweck | **Test-Datengenerator** (nur Sim/Dev) | **Produkt** (läuft auch mit echten Webcam-Fotos!) |
|
||||
| Änderungsrate | selten | häufig |
|
||||
| CI-tauglich | nein (schwer, GPU) | ja (schnell, headless) |
|
||||
|
||||
Das ist keine Kosmetik: Die **Pipeline ist das eigentliche Deliverable** (Roboter-Pose
|
||||
aus Fotos) und wird real deployed; der Renderer ist nur Werkzeug zur Testdaten-Erzeugung.
|
||||
Getrennt heißt: die Pipeline bleibt schlank, schnell CI-testbar und ohne Blender-Ballast
|
||||
deploybar; der Renderer wird nur dort gestartet, wo eine GPU steht.
|
||||
|
||||
**Datenaustausch** zwischen beiden: gemeinsames Volume (Phase 1–3), später Object-Storage
|
||||
(MinIO/S3) im verteilten Betrieb.
|
||||
|
||||
## Technische Schlüsselpunkte (bisher nicht in der Roadmap)
|
||||
|
||||
1. **cv2 in Blenders Python:** `render_robot.py` importiert `cv2` (ArUco-Generierung).
|
||||
Blender bringt sein *eigenes* gebündeltes Python mit — `opencv-python` muss **dort**
|
||||
installiert werden (`<blender>/python/bin/python -m pip install opencv-python`),
|
||||
nicht ins System-Python. Häufige Stolperfalle.
|
||||
2. **ArUco = opencv-contrib:** Die Pipeline nutzt `cv2.aruco`. Im Pipeline-Container
|
||||
`opencv-contrib-python-headless` verwenden (nicht Basis-`opencv-python`), Version pinnen.
|
||||
3. **robot.json-Mutation ist im Parallelbetrieb ein Race:** `render_Loop.py` schreibt
|
||||
pro Render in die *gemeinsame* `robot.json` (Kamera, Pose, Auflösung). Laufen mehrere
|
||||
Render-Jobs parallel auf einem Node, überschreiben sie sich gegenseitig. Im Job-Modell
|
||||
muss jeder Job seine Parameter aus dem **Job-Payload** bekommen und in eine **eigene
|
||||
temporäre Config** schreiben — nicht in die geteilte robot.json. (Architektur-Fix,
|
||||
gehört *vor* Phase 4.)
|
||||
4. **GPU im Container & Scheduler:** `--gpus all` + NVIDIA Container Toolkit; Nomad braucht
|
||||
das GPU-Device-Plugin, damit Render-Jobs nur auf GPU-Nodes landen. CPU-Fallback (Cycles
|
||||
`device='CPU'`) als Sicherheitsnetz behalten.
|
||||
5. **Versionen pinnen:** Blender 4.5.x exakt, `requirements.txt` mit festen Versionen
|
||||
(numpy/scipy/opencv) — sonst driften die Mess-Ergebnisse (vgl. der fy-Intrinsik-Bug).
|
||||
6. **Job-Granularität:** `{"jobType":"blender-render","pose":8}` rendert 7 Kameras pro Job.
|
||||
Feinkörniger (1 Job = 1 Kamera) parallelisiert besser über mehrere Nodes — abwägen.
|
||||
|
||||
## Empfehlung: MVP vor Nomad
|
||||
|
||||
Redis + Nomad ist die richtige End-Vision, aber als Zwischenstufe genügt **docker-compose
|
||||
mit zwei Images + Profiles** (Renderer on-demand via `docker compose run`, Pipeline als
|
||||
schneller Service / CI-Step). Damit sind getrennte Container + Phase 1–3 produktiv nutzbar,
|
||||
bevor die verteilte Orchestrierung (Phase 5–8) aufgebaut wird.
|
||||
|
||||
---
|
||||
|
||||
# Phase 1 – Dockerisierung der bestehenden Rendering-Pipeline
|
||||
|
||||
## Ziel
|
||||
|
||||
Die aktuelle Blender-Pipeline läuft vollständig innerhalb eines Docker-Containers.
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [x] Dockerfile erstellen → **in zwei aufteilen:** `Dockerfile.renderer` (Blender) + `Dockerfile.pipeline` (slim Python)
|
||||
* [x] docker-compose.yaml erstellen
|
||||
* [ ] cv2 in Blenders gebündeltem Python installieren (für ArUco-Generierung)
|
||||
* [ ] requirements.txt für den Pipeline-Container (numpy, scipy, opencv-contrib-python-headless), Versionen gepinnt
|
||||
* [ ] Blender 4.5 Container erfolgreich starten
|
||||
* [ ] render_loop.py innerhalb des Containers ausführen
|
||||
* [ ] render_robot.py innerhalb des Containers ausführen
|
||||
* [ ] STL-Import validieren
|
||||
* [ ] PNG-Ausgabe validieren
|
||||
* [ ] NPZ-Ausgabe validieren
|
||||
* [ ] Pipeline auf PNG-Ausgaben ermöglichen
|
||||
* [ ] markers.json validieren
|
||||
|
||||
### Ergebnis
|
||||
|
||||
Zwei Container: `blender-renderer` erzeugt Bilder/npz/Ground-Truth, `pose-pipeline`
|
||||
wertet sie aus — beide reproduzierbar, über ein gemeinsames Daten-Volume verbunden.
|
||||
|
||||
---
|
||||
|
||||
# Phase 2 – Pfad-Unabhängigkeit
|
||||
|
||||
## Ziel
|
||||
|
||||
Alle absoluten Benutzerpfade entfernen.
|
||||
|
||||
### Aktuelle Situation
|
||||
|
||||
Beispiel:
|
||||
|
||||
```python
|
||||
Path.home() / "SynologyDrive" / ...
|
||||
```
|
||||
|
||||
### Ziel
|
||||
|
||||
Container-interne Pfade verwenden:
|
||||
|
||||
```text
|
||||
/workspace/data
|
||||
/workspace/setup
|
||||
/workspace/output
|
||||
```
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [ ] ROBOT_JSON_FILE auf Containerpfade umstellen
|
||||
* [ ] OUTPUT_FILE auf Containerpfade umstellen
|
||||
* [ ] STL-Suche auf Containerpfade umstellen
|
||||
* [ ] Konfiguration über Environment-Variablen ermöglichen
|
||||
* [ ] **render_robot.py: Config-Pfad per env (`ROBOT_JSON`)** statt hardcodiert; und
|
||||
**render_Loop.py: pro Render eine *temporäre* Config schreiben** statt die geteilte
|
||||
robot.json zu mutieren (Voraussetzung für parallele Jobs, siehe Schlüsselpunkt 3)
|
||||
* [ ] BLENDER_EXE per env/PATH (aktuell hardcodierter Windows-Pfad)
|
||||
|
||||
### Ergebnis
|
||||
|
||||
Die Pipeline ist vollständig unabhängig vom lokalen Benutzerprofil und parallel-tauglich.
|
||||
|
||||
---
|
||||
|
||||
# Phase 3 – Repository-Struktur bereinigen
|
||||
|
||||
## Ziel
|
||||
|
||||
Klare Trennung zwischen Code, Daten und Ergebnissen.
|
||||
|
||||
### Zielstruktur
|
||||
|
||||
```text
|
||||
appRobotRendering/
|
||||
|
||||
├── data/
|
||||
│ ├── robot/
|
||||
│ ├── simulation/
|
||||
│ └── surfaces/
|
||||
│
|
||||
├── setup/
|
||||
│ └── generateSets/
|
||||
│ ├── render_loop.py
|
||||
│ ├── render_robot.py
|
||||
│ ├── Dockerfile
|
||||
│ └── docker-compose.yaml
|
||||
│
|
||||
├── jobs/
|
||||
│
|
||||
└── output/
|
||||
```
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [ ] Verzeichnisstruktur vereinheitlichen
|
||||
* [ ] Dokumentation ergänzen
|
||||
* [ ] Mountpoints definieren
|
||||
|
||||
---
|
||||
|
||||
# Phase 4 – Job-Modell einführen
|
||||
|
||||
## Ziel
|
||||
|
||||
Rendering-Aufträge werden als eigenständige Jobs beschrieben.
|
||||
|
||||
### Beispiel
|
||||
|
||||
```json
|
||||
{
|
||||
"jobType": "blender-render",
|
||||
"pose": 8
|
||||
}
|
||||
```
|
||||
|
||||
### Spätere Erweiterungen
|
||||
|
||||
```json
|
||||
{
|
||||
"jobType": "dataset-generation"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"jobType": "stl-conversion"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"jobType": "ai-training"
|
||||
}
|
||||
```
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [ ] Job-Format definieren
|
||||
* [ ] Job-Metadaten definieren
|
||||
* [ ] Retry-Konzept definieren
|
||||
* [ ] Statusmodell definieren
|
||||
|
||||
### Status
|
||||
|
||||
```text
|
||||
queued
|
||||
running
|
||||
completed
|
||||
failed
|
||||
timeout
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Phase 5 – Redis als Queue
|
||||
|
||||
## Ziel
|
||||
|
||||
Entkopplung zwischen Auftragserzeugung und Ausführung.
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [ ] Redis bereitstellen
|
||||
* [ ] Job-Queue definieren
|
||||
* [ ] Job-Status speichern
|
||||
* [ ] Retry-Mechanismus definieren
|
||||
|
||||
### Hinweis
|
||||
|
||||
Redis startet keine Worker.
|
||||
|
||||
Redis dient ausschließlich als:
|
||||
|
||||
* Queue
|
||||
* Statusspeicher
|
||||
* Kommunikationsschicht
|
||||
|
||||
---
|
||||
|
||||
# Phase 6 – Nomad Scheduler
|
||||
|
||||
## Ziel
|
||||
|
||||
Container werden nur bei tatsächlichem Bedarf gestartet.
|
||||
|
||||
### Architektur
|
||||
|
||||
```text
|
||||
Job Producer
|
||||
│
|
||||
▼
|
||||
|
||||
Redis
|
||||
│
|
||||
▼
|
||||
|
||||
Nomad
|
||||
│
|
||||
▼
|
||||
|
||||
Docker Container
|
||||
```
|
||||
|
||||
### Aufgaben
|
||||
|
||||
* [ ] Nomad Server aufsetzen
|
||||
* [ ] Worker-Nodes registrieren
|
||||
* [ ] Docker Driver aktivieren
|
||||
* [ ] Batch-Jobs definieren
|
||||
|
||||
### Ergebnis
|
||||
|
||||
Nomad entscheidet:
|
||||
|
||||
* welcher Node frei ist
|
||||
* welcher Container gestartet wird
|
||||
* wann ein Container beendet wird
|
||||
|
||||
---
|
||||
|
||||
# Phase 7 – Blender als Nomad Batch Job
|
||||
|
||||
## Ziel
|
||||
|
||||
Blender läuft nur während der Bearbeitung eines Auftrags.
|
||||
|
||||
### Beispiel
|
||||
|
||||
```text
|
||||
Job:
|
||||
blender-render
|
||||
|
||||
Container:
|
||||
approbot/blender-renderer:latest
|
||||
```
|
||||
|
||||
Ablauf:
|
||||
|
||||
1. Job wird eingereicht
|
||||
2. Nomad startet Blender-Container
|
||||
3. Rendering läuft
|
||||
4. Ergebnisse werden gespeichert
|
||||
5. Container beendet sich
|
||||
6. Ressourcen werden freigegeben
|
||||
|
||||
### Ergebnis
|
||||
|
||||
Keine dauerhaft laufenden Blender-Worker.
|
||||
|
||||
---
|
||||
|
||||
# Phase 8 – Multi-Container Plattform
|
||||
|
||||
## Ziel
|
||||
|
||||
Beliebige Jobtypen auf derselben Infrastruktur ausführen.
|
||||
|
||||
### Beispiele
|
||||
|
||||
#### Blender Rendering
|
||||
|
||||
```text
|
||||
Container:
|
||||
approbot/blender-renderer
|
||||
```
|
||||
|
||||
#### AI Training
|
||||
|
||||
```text
|
||||
Container:
|
||||
approbot/trainer
|
||||
```
|
||||
|
||||
#### STL Processing
|
||||
|
||||
```text
|
||||
Container:
|
||||
approbot/stl-worker
|
||||
```
|
||||
|
||||
#### Dataset Generation
|
||||
|
||||
```text
|
||||
Container:
|
||||
approbot/dataset-worker
|
||||
```
|
||||
|
||||
### Ergebnis
|
||||
|
||||
Der verwendete Container wird durch den Jobtyp bestimmt.
|
||||
|
||||
---
|
||||
|
||||
# Zielarchitektur
|
||||
|
||||
```text
|
||||
Nomad
|
||||
│
|
||||
|
||||
┌────────────────┼────────────────┐
|
||||
│ │ │
|
||||
|
||||
Blender Job AI Job Dataset Job
|
||||
│ │ │
|
||||
|
||||
Blender Training Dataset Worker
|
||||
Container Container Container
|
||||
|
||||
└────────────────┼────────────────┘
|
||||
│
|
||||
|
||||
Docker
|
||||
|
||||
│
|
||||
|
||||
Worker Nodes (PCs)
|
||||
```
|
||||
|
||||
Eigenschaften:
|
||||
|
||||
* keine dauerhaft laufenden Blender-Container
|
||||
* unterschiedliche Container pro Jobtyp
|
||||
* horizontale Skalierung auf mehrere PCs
|
||||
* saubere Trennung von Scheduling und Ausführung
|
||||
* zukünftige Erweiterbarkeit für beliebige Workloads
|
||||
|
||||
---
|
||||
|
||||
# Offene Punkte / nicht vergessen
|
||||
|
||||
* **Cluster-Storage:** geteiltes NFS/Volume (einfach) vs. Object-Storage MinIO/S3
|
||||
(entkoppelt Nodes, skaliert). Ab >1 Worker-Node bevorzugt Object-Storage.
|
||||
* **robot.json als geteilter Mutable-State auflösen** (Schlüsselpunkt 3) — Voraussetzung
|
||||
für parallele Render-Jobs auf einem Node.
|
||||
* **Reproduzierbarkeit:** Blender- und Python-Versionen pinnen; `requirements.txt` einchecken.
|
||||
* **GPU-Headless:** prüfen, ob Cycles im Container EGL braucht; sonst CPU-Fallback verifizieren.
|
||||
* **CI-Hook:** Pipeline-Container in CI → `benchmark/run_benchmark.py` gegen Ground-Truth
|
||||
bei jedem Commit (schnell, ohne Blender) — fängt Regressionen wie den fy-Bug automatisch.
|
||||
* **Monitoring/Logs:** Job-Logs zentral (stdout → Nomad/Loki), Render-Zeiten messen.
|
||||
* **Image-Registry:** private Registry (Harbor o. Ä.) für die `approbot/*`-Images.
|
||||
Reference in New Issue
Block a user