feat(storage): add verified offline MinIO migration pilot
This commit is contained in:
@@ -8,4 +8,5 @@ Diese Dokumentation unterstützt dich bei der täglichen Nutzung von FEDEO.
|
||||
- [Fach- und Technikkonzept für das Lagersystem](./lagersystem-konzept.md)
|
||||
- [Zentraler Push-Server für Selfhost-Instanzen](./zentraler-push-server.md)
|
||||
- [Konzept zum Austausch von MinIO](./minio-austausch-konzept.md)
|
||||
- [MinIO-Umstellung: ausführbarer Pilot](./minio-umstellung-pilot.md)
|
||||
- [Konzept für föderierte Chats und externe Projektteilnehmer](./chat-foederation-konzept.md)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
Stand: 25. September 2026. Status: Entscheidungsvorschlag auf Basis des FEDEO-Codes bei Commit `29155f91` und der unten verlinkten Herstellerquellen. Eine Migration, ein Kompatibilitätstest mit einem Ersatzserver oder eine Änderung an einer laufenden Instanz wurde für dieses Konzept nicht durchgeführt.
|
||||
|
||||
**Fortschreibung vom 27. September 2026:** Ein ausführbarer, isoliert getesteter
|
||||
Migrationspilot ist hinzugekommen. Durchführung, Testnachweise und noch offene
|
||||
Freigaben stehen in [MinIO-Umstellung: Pilot](minio-umstellung-pilot.md).
|
||||
Die folgenden Abschnitte bleiben das Zielbild für den vollständigen Standardbetrieb.
|
||||
|
||||
## 1. Empfehlung und Umfang
|
||||
|
||||
**SeaweedFS Open Source wird der bevorzugte Kandidat für den FEDEO-Dateispeicher.** Ziel ist ein einzelner Container auf dem bisherigen Docker-Host mit S3-Schnittstelle, privaten Buckets und persistentem lokalen Speicher. Die Freigabe erfolgt erst nach den unter Abschnitt 10 beschriebenen Tests mit einem festgelegten Release und Image-Digest.
|
||||
|
||||
226
docs/minio-umstellung-pilot.md
Normal file
226
docs/minio-umstellung-pilot.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# MinIO → SeaweedFS: betreuter Pilot auf einer Installer-Instanz
|
||||
|
||||
Stand: 27. September 2026. Dieser Ablauf ergänzt das
|
||||
[Austauschkonzept](minio-austausch-konzept.md) um ausführbare Werkzeuge.
|
||||
Er übernimmt den Speicher einer vorhandenen Installation, beispielsweise 3.3.0,
|
||||
mit unveränderten Anwendungsimages und ohne Datenbankschemamigration.
|
||||
|
||||
**Vor dem ersten Wartungsfenster nur `load-images` und `plan` ausführen.**
|
||||
Die Vorprüfung ermittelt die bislang unbekannten Größen und liefert eine
|
||||
kompakte Ausgabe zum gemeinsamen Prüfen. Sie stoppt keine Anwendungscontainer.
|
||||
Ein Zugriff auf die konkrete Kundeninstanz wurde bei der Entwicklung nicht ausgeführt.
|
||||
|
||||
## Was der Pilot leistet und wo seine Grenze liegt
|
||||
|
||||
- Vorhandenes MinIO verwenden; kein Abruf von `minio/minio` oder `mc` erforderlich.
|
||||
- Feste SeaweedFS-Version 4.47; Offline-Images, SHA-256-geprüftes Paket.
|
||||
- Alle Objekte des einzigen FEDEO-Buckets übernehmen, inklusive Exporte und
|
||||
Objekte ohne aktuellen Datenbankverweis. Schlüssel und Metadaten bleiben erhalten.
|
||||
- Alle bekannten Schreiber anhalten, ihre automatischen Neustarts sperren,
|
||||
PostgreSQL dumpen und MinIO kalt sichern. Die alten Daten bleiben erhalten.
|
||||
- Kopie, vollständigen Inhaltsvergleich und tatsächlichen SeaweedFS-Restore in
|
||||
ein frisches Verzeichnis prüfen. Unbekannte Zielobjekte werden nicht gelöscht.
|
||||
- Den S3-Vertrag zusätzlich mit dem **tatsächlich installierten Backendimage**
|
||||
ausführen. Dabei startet nur das Prüfprogramm, kein FEDEO-Backend.
|
||||
- Erst nach diesen Prüfungen den Alias `minio` exklusiv an SeaweedFS vergeben
|
||||
und die unveränderte Anwendung wieder starten.
|
||||
|
||||
**Der Pilot ist noch kein neuer Standardinstaller und kein reguläres
|
||||
FEDEO-Release.** Der bisherige Anwendungs-Updater kennt nur MinIO. Seine Aufträge
|
||||
bleiben nach der Umstellung bewusst über `recoveryRequired` gesperrt, bis ein
|
||||
getesteter Provider-Adapter installiert wird. Diesen Zustand nicht mit dem alten
|
||||
`resolve` oder durch Löschen der Statusdatei aufheben. Ein alter Installer oder
|
||||
ein altes Release-Compose darf die umgestellte Installation nicht überschreiben.
|
||||
|
||||
FEDEO 3.3.0 kann im Systemstatus weiterhin den MinIO-spezifischen Health-Endpunkt
|
||||
abfragen und dadurch den Dateispeicher als gestört anzeigen. Die tatsächliche
|
||||
Funktionsprüfung erfolgt im Pilot über signierte S3-Operationen. Herstellerneutrale
|
||||
Oberflächenchecks, eine Migrationskarte in der Oberfläche, automatische Updates
|
||||
auf SeaweedFS und der Standardinstaller sind nachfolgende Arbeitspakete.
|
||||
Wer diese Einschränkungen noch nicht im Betrieb tragen möchte, führt zunächst
|
||||
nur die Vorprüfung durch und bleibt mit der Instanz auf MinIO.
|
||||
|
||||
## Voraussetzungen, die der Plan prüft
|
||||
|
||||
Linux amd64, Python ab 3.10, lokaler Docker-Daemon, Docker Compose und `tar`/`du`.
|
||||
Die Installation muss laufen und aus dem Installer stammen: lokale Verzeichnisse
|
||||
`postgres/` und `minio/`, interner Endpunkt `http://minio:9000`, S3-Zugang wie beim
|
||||
Installer aus `MINIO_ROOT_*`, keine externen Secret-Provider, keine zusätzlichen
|
||||
MinIO-Ports, Datenmounts oder unbekannten Container im internen Netz.
|
||||
Bekannte lokale Matrix-Dienste werden erhalten, während der Kopie angehalten und
|
||||
mit ihren Daten kalt gesichert. Andere Zusatzdienste/Compose-Overrides blockieren
|
||||
den Pilot und benötigen einen angepassten Plan.
|
||||
|
||||
Der S3-Prüfer blockiert zusätzliche Buckets, Versionierung einschließlich alter
|
||||
Versionen/Delete-Marker, Object Lock, konfigurierte Serververschlüsselung,
|
||||
Objekt-/Bucket-Tags, eigene Policies/ACLs, Lifecycle, Replikation, Benachrichtigungen,
|
||||
CORS und offene Multipart-Uploads. Unklare S3-Fehler werden nicht als „nicht vorhanden“
|
||||
gewertet. Datei-/Verzeichniskonflikte und normalisierungsgefährdete Schlüssel wie
|
||||
`a//b`, `a/../b` und Verzeichnismarker blockieren ebenfalls.
|
||||
|
||||
Die bekannten lokalen MinIO-Metadaten werden zusätzlich geprüft (`xl-single`,
|
||||
Metadatenformat 3). MinIO kann bei gleichzeitigem `a` und `a/b` einen Schlüssel
|
||||
aus der S3-Liste verbergen, obwohl er per GET erreichbar bleibt. Bei gestopptem
|
||||
MinIO muss deshalb die Menge lokaler `xl.meta`-Objektpfade exakt mit dem S3-Inventar
|
||||
übereinstimmen. Andere Speicherformate oder Abweichungen blockieren die Umschaltung.
|
||||
|
||||
Getestete Pilotgrenzen: **200.000 Objekte, höchstens 256 MiB je Objekt**.
|
||||
Die Kapazitätsabschätzung berücksichtigt Quellsicherung, neues und wiederhergestelltes
|
||||
Ziel, Metadatenreserve pro Objekt, DB-Dump, Offline-Images, Spool und 5 GiB Reserve.
|
||||
Nach dem Schreibstopp wird das Inventar erneut ermittelt. Es gibt keine Annahme,
|
||||
dass eine unbekannte freie Kapazität ausreichend ist.
|
||||
|
||||
Externe Schreiber lassen sich nicht allein anhand von Docker erkennen. Vor
|
||||
`migrate --writers-exclusive` muss feststehen, dass keine anderen Anwendungen,
|
||||
direkten DB-/S3-Clients oder manuellen Compose-Aufträge parallel schreiben.
|
||||
|
||||
## Paket erstellen und auf den Host übertragen
|
||||
|
||||
Im Entwicklungscheckout mit Docker:
|
||||
|
||||
```sh
|
||||
bash scripts/storage/build-pilot.sh
|
||||
```
|
||||
|
||||
Ergebnis: `.release/storage-pilot.tar.gz` samt `.sha256` und entpacktem Paket.
|
||||
Das Archiv enthält Hostprogramme, Dokumentation und beide benötigten Zielimages.
|
||||
Es enthält keine Instanz-Zugangsdaten, keine Kundendateien und kein neues MinIO.
|
||||
Die Build-Phase darf Images herunterladen; alle Schritte auf dem Zielhost starten
|
||||
Container mit `--pull never`.
|
||||
|
||||
Archiv und Prüfsumme über den üblichen Administrationsweg auf den Docker-Host
|
||||
kopieren. Dort die tatsächliche Prüfsumme mit der mitgelieferten vergleichen,
|
||||
beispielsweise bei Ablage unter `/root`:
|
||||
|
||||
```sh
|
||||
cd /root
|
||||
sha256sum storage-pilot.tar.gz
|
||||
tar -xzf storage-pilot.tar.gz
|
||||
cd storage-pilot
|
||||
sudo python3 pilot.py load-images
|
||||
sudo python3 pilot.py plan --directory /opt/fedeo
|
||||
```
|
||||
|
||||
Die Ausgabe von `plan` kann in den Supportdialog kopiert werden. Sie enthält
|
||||
Phase, Anwendungsversion, Objektanzahl, Objektbytes und benötigten/verfügbaren
|
||||
Platz; keine Passwörter oder Dateinamen. Falls der Installer in ein anderes
|
||||
Verzeichnis installiert wurde, bei jedem Befehl denselben Pfad angeben.
|
||||
|
||||
Ein Plan verändert keine Quelldateien oder fachlichen Daten. Er legt geschützte
|
||||
Migrationsdateien unter `.updates/storage-migration/` und einen lokalen Image-Tag
|
||||
zur Aufbewahrung des Hilfsimages an. Die `storage/`-Datenablage entsteht erst beim
|
||||
Migrationslauf. Das Paket bleibt bis zum Abschluss verfügbar; nicht mitten im
|
||||
Auftrag neu bauen oder austauschen.
|
||||
|
||||
## Wartungsfenster: kopieren, prüfen, dann freigeben
|
||||
|
||||
Erst nach Prüfung der Planausgabe und Abstimmung des Wartungsfensters:
|
||||
|
||||
```sh
|
||||
sudo python3 pilot.py migrate --directory /opt/fedeo --writers-exclusive
|
||||
sudo python3 pilot.py status --directory /opt/fedeo
|
||||
```
|
||||
|
||||
`migrate` endet bei `phase: verified`. Die Anwendung ist dann **weiter angehalten**.
|
||||
Es hat noch keine fachlichen Schreibzugriffe auf SeaweedFS gegeben.
|
||||
Der Lauf besitzt dieselbe exklusive Sperre wie der Host-Updater.
|
||||
|
||||
Die Umschaltung ist ein eigener Befehl:
|
||||
|
||||
```sh
|
||||
sudo python3 pilot.py activate --directory /opt/fedeo
|
||||
```
|
||||
|
||||
`activate` liest Quelle und Ziel nochmals vollständig, stoppt MinIO, entfernt
|
||||
dessen internen Netzwerkanschluss, sichert SeaweedFS kalt und startet einen
|
||||
separaten Restore-Container mit frisch entpackten Daten. Alle Objekt-Hashes und
|
||||
Metadaten müssen dort stimmen. Danach erhält das aktive Ziel allein den Alias
|
||||
`minio`, und die S3-Vertragstests laufen erneut, auch mit dem Original-Backend-SDK.
|
||||
|
||||
**Vor dem Start irgendeines fachlichen Schreibers** persistiert das Programm
|
||||
`writesReleased: true`. Erst danach werden Backend/Hintergrunddienste und zuletzt
|
||||
der öffentliche Proxy gestartet. Ein Fehler beim Neustart führt nicht zu einem
|
||||
automatischen Rückfall auf den nun möglicherweise veralteten Quellspeicher.
|
||||
|
||||
Anschließend auf der Instanz prüfen: Anmeldung, bestehender Download, PDF-Vorschau,
|
||||
neuer Upload mit erneutem Download, WebDAV, DATEV/SEPA und Mandantenexport/-import.
|
||||
Bei zwei Testmandanten auch die unveränderten Zugriffsgrenzen kontrollieren.
|
||||
Bereits ausgegebene S3-Links sind zusätzlich über ihren tatsächlichen Zugriffsweg
|
||||
zu prüfen; ein interner Docker-Alias macht interne URLs nicht öffentlich erreichbar.
|
||||
|
||||
## Fehler und Wiederaufnahme
|
||||
|
||||
| Zustand | Vorgehen |
|
||||
| --- | --- |
|
||||
| `planned` | Instanz läuft noch; Wartungsfenster vorbereiten. |
|
||||
| `freezing`, `backing_up`, `backed_up`, `copying`, `verifying`, `verified` | `migrate --writers-exclusive` setzt fort. Quelle, Schreibstopp, Backups und Inhalte werden erneut geprüft. |
|
||||
| `cutover`, `restore_testing` | `activate` setzt die noch nicht freigegebene Umschaltung fort; alternativ Rückkehr. |
|
||||
| `released` nach fehlgeschlagenem Start | `resume-start` versucht denselben Zielstand erneut. Keine einfache Rückkehr mehr. |
|
||||
| `complete` | SeaweedFS aktiv; alte Daten und Backups weiter aufbewahren. |
|
||||
| `rolled_back` | MinIO wieder aktiv. Vor einem neuen Versuch einen neuen betreuten Plan anlegen; bestehende Beweise nicht löschen. |
|
||||
|
||||
Vor der Schreibfreigabe ist die Rückkehr ausführbar:
|
||||
|
||||
```sh
|
||||
sudo python3 pilot.py rollback --directory /opt/fedeo
|
||||
```
|
||||
|
||||
Sie stoppt das Ziel, stellt Compose, den alten exklusiven Netzwerkanschluss und
|
||||
die ursprünglichen Neustartrichtlinien wieder her und startet die vorher laufenden
|
||||
Container. Quelldaten und DB bleiben unverändert. Nach `writesReleased: true`
|
||||
verweigert das Programm diesen Befehl. Dann braucht eine Rückkehr eine gesonderte
|
||||
Rückmigration einschließlich Löschungen oder die bewusste Wiederherstellung eines
|
||||
zusammengehörigen Backups.
|
||||
|
||||
## Protokolle, Sicherungen und Betriebsdaten
|
||||
|
||||
`status` ist die kompakte Ausgabe ohne Geheimnisse. Geschützte Einzelheiten liegen
|
||||
unter `/opt/fedeo/.updates/storage-migration/`:
|
||||
|
||||
- `state.json`: Phase, Container-/Image-Identitäten und dauerhafte Schreibgrenze.
|
||||
- `commands.log`, `progress.jsonl`: Hostfehler und letzter Werkzeugfortschritt.
|
||||
- `copy/inventory.json`, `copy/objects.jsonl`, `copy/verified.json`: vollständiges
|
||||
Inventar und überprüfte Objekt-Hashes. Diese Dateien enthalten Dateinamen/Metadaten.
|
||||
- `backup/database.dump`, `globals.sql`, `files.tar`, `images.tar`, `complete.json`:
|
||||
zusammengehörige Quellsicherung mit Prüfsummen. Der DB-Dump wird mit `pg_restore --list`
|
||||
geprüft; ein vollständiger fachlicher DB-Restore bleibt eine gesonderte DR-Prüfung.
|
||||
- `backup/seaweedfs.tar`: kalt gesicherter neuer Speicher samt Konfiguration;
|
||||
sein SHA-256 und erfolgreicher echter Restore werden im Zustand festgehalten.
|
||||
|
||||
Die neue persistente Ablage ist `storage/seaweedfs/`, die geschützte Konfiguration
|
||||
`storage/config/`. SeaweedFS bindet Verwaltung, Filer und Volume-APIs an Loopback
|
||||
im Container; im internen Docker-Netz liegt ausschließlich S3 auf Port 9000.
|
||||
Ein Startwrapper verweigert fehlende oder veränderte Zugangskonfiguration.
|
||||
Die Anwendungsidentität erhält nur Lese-, Schreib- und Listenrechte für ihren Bucket.
|
||||
|
||||
Für spätere Sicherungen **SeaweedFS anhalten und `storage/` vollständig sichern**,
|
||||
einschließlich Filer-Metadaten, Masterzustand, Objektdaten, Konfiguration und passendem
|
||||
Image. Die DB-Sicherung muss zum selben Schreibstopp gehören. Die Sicherungen auf
|
||||
demselben Host anschließend auf das vorgesehene externe Backupziel übernehmen.
|
||||
MinIO-Daten, alte Container, Test-Restores und Offline-Images werden vom Pilot
|
||||
nicht automatisch gelöscht.
|
||||
|
||||
## Nachgewiesene Tests und ausstehende Freigaben
|
||||
|
||||
Der lokale S3-Test verwendet das offizielle MinIO-Release-Binary vom 7. September
|
||||
2025 und SeaweedFS 4.47 mit festem Digest. 1.005 Objekte / 268.446.382 Bytes,
|
||||
einschließlich 256-MiB-Grenzdatei, Pagination, Sonderzeichen, Metadaten, leeren
|
||||
Dateien, Streaming, 24-Stunden-Signaturen, fremdem Bucket und ungültigen Zugängen
|
||||
werden geprüft. Beschädigte Zielobjekte werden erkannt und beim Fortsetzen
|
||||
erneut kopiert; der kalte Restore wird vollständig gelesen und verglichen.
|
||||
Ein Lauf der Kopier-/Prüf-/Restore-Sequenz dauerte lokal ungefähr 65 Sekunden;
|
||||
Testhost: Linux, 16 logische CPUs, rund 29 GiB RAM für Docker, lokaler NVMe-Speicher.
|
||||
Dies ist keine Laufzeitzusage für die Instanz.
|
||||
|
||||
Das Hilfs-Lockfile enthält den übernommenen vollständigen SDK-Abhängigkeitsbaum
|
||||
des Backends, nicht nur dieselbe oberste Versionsnummer. Beim Pilot wird außerdem
|
||||
das konkrete installierte Backendimage gegen das Ziel geprüft.
|
||||
|
||||
Die Host-Integrationstests verwenden echte Speicher- und PostgreSQL-Container,
|
||||
aber künstliche Anwendungsprozesse. Rückkehr vor Schreibfreigabe sowie vollständige
|
||||
Umschaltung mit Restore und gesperrter Rückkehr nach Schreibfreigabe wurden erfolgreich
|
||||
durchlaufen. Die fachliche Abnahme von FEDEO auf der
|
||||
konkreten Instanz, ein physischer Hostneustart während jeder Phase, das reguläre
|
||||
Anwendungsupdate auf SeaweedFS und die vollständige Wiederherstellung auf einem
|
||||
anderen Host sind damit noch nicht nachgewiesen. Deshalb bleibt dieser Stand ein
|
||||
betreuter Pilot; die allgemeinen Freigabekriterien des Konzepts gelten weiter.
|
||||
Reference in New Issue
Block a user