restic statt Eigenbau (Content-defined Chunking fuer Dedup, verschluesseltes Repository ab Werk, geprueftes Tooling). internal/objectbackup wrapt restic init/backup/check/forget ueber os/exec, cmd/objectbackup-cli fuer systemd-Timer (stuendliche Sicherung, woechentliche Vollstaendigkeitspruefung, taegliche Rotation). Auf 192.168.1.131 real verifiziert (kein Mock): zweiter Lauf gegen unveraenderten Bestand ueberraegt nichts (files_new=0), zwei identische Dateien erzeugen nachweislich nur 1 data_blob (echter Dedup-Nachweis), absichtlich gekipptes Byte in einer Pack-Datei wird von check --read-data zuverlaessig erkannt. Echt verdrahtet: 3 systemd-Timer installiert+ aktiviert, jeder Dienst einmal end-to-end via systemctl start ausgeloest. Im selben Rutsch BAK-01-Fund korrigiert: NEXARCH_BACKUP_DIR zeigte auf /var/backups/nexarch (Root-Dateisystem, kein Dataset) statt auf das persistente ZFS-Dataset /var/nexarch-archiv - korrigiert, erneut ausgeloest, landet nachweislich am richtigen Ort. objectbackup-cli-Repository liegt von Anfang an korrekt dort. Siehe archive/docs/BAK-02-PRUEFPROTOKOLL.md fuer alle Pruefungsergebnisse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
94 lines
5.1 KiB
Markdown
94 lines
5.1 KiB
Markdown
# BAK-02 – Prüfprotokoll: Objekt-Storage-Backup/Snapshots
|
||
|
||
Welle 1, keine Vorbedingungen.
|
||
|
||
## Grundsatzentscheidung: restic statt Eigenbau
|
||
|
||
Nutzerentscheidung: restic statt einer Neuimplementierung, weil restic alle
|
||
vier Akzeptanzkriterien mit ausgereiftem, breit geprüftem Tooling erfüllt
|
||
(Content-defined Chunking für Dedup, `check --read-data` für
|
||
Vollständigkeit, `forget --keep-last` für Rotation, Repository-Verschlüsselung
|
||
ab Werk). Installiert via `apt-get install restic` (Version 0.18.0).
|
||
|
||
Backup-Quelle ist ein lokaler Verzeichnisbaum — für den FDN-03-`LocalDriver`
|
||
direkt dessen Basisverzeichnis. Für S3-gestützte Produktions-Deployments
|
||
(Betriebsmodus 2/3 aus `STORAGE-KONZEPT.md` Abschnitt 6.2) wäre ein
|
||
vorgelagerter Sync-Schritt (z. B. `rclone`) nötig, um Bucket-Inhalte lokal
|
||
zu spiegeln, bevor restic sie sichert — restic sichert Dateibäume, keine
|
||
S3-Buckets direkt. Das bleibt hier bewusst unimplementiert (kein konkreter
|
||
S3-Produktionsbestand vorhanden, der das aktuell erfordert), aber
|
||
architektonisch vorgesehen und dokumentiert (`README.md`).
|
||
|
||
## Umsetzung
|
||
|
||
- `internal/objectbackup.InitRepo` — idempotent, erkennt "bereits
|
||
initialisiert" am `restic init`-Fehlertext statt zu scheitern.
|
||
- `internal/objectbackup.Backup` — `restic backup --json`, parst die
|
||
`summary`-Zeile (mehrere JSON-Zeilen in der Ausgabe, gezielt die mit
|
||
`message_type=="summary"` gesucht).
|
||
- `internal/objectbackup.Check` — `restic check [--read-data]` (Akzeptanz-
|
||
kriterium 3: Vollständigkeitsprüfung).
|
||
- `internal/objectbackup.Forget` — `restic forget --keep-last N --prune`
|
||
(Rotation).
|
||
- `cmd/objectbackup-cli` — `backup <dir>`/`check`/`rotate`, aufgerufen von
|
||
systemd-Timern (stündlich/wöchentlich/täglich).
|
||
|
||
## Prüfungen
|
||
|
||
| # | Prüfung | Ergebnis |
|
||
|---|---|---|
|
||
| 1 | Zweiter Sicherungslauf nach unverändertem Bestand überträgt keine Daten erneut | **bestanden** — `TestBackup_UnchangedSecondRunTransmitsNothingNew`: zweiter Lauf gegen unveränderten Bestand liefert `files_new=0`, `files_changed=0`, `files_unmodified=1` |
|
||
| 2 | Zwei identische Testdateien belegen nachweislich nur einmal Speicherplatz | **bestanden** — `TestBackup_DeduplicatesIdenticalContent`: zwei Dateien mit identischem Inhalt erzeugen `data_blobs=1`, nicht 2 — echter Dedup-Nachweis über restics Content-defined Chunking, nicht nur Namensvergleich |
|
||
| 3 | Vollständigkeitsprüfung erkennt ein fehlendes Objekt in der Sicherung | **bestanden** — `TestCheck_DetectsCorruptedPack`: ein Byte in einer echten Repository-Pack-Datei gekippt, `Check(readData=true)` schlägt danach fehl (unbeschädigt zuvor erfolgreich) — dieselbe Vorgehensweise wie die manuelle Recherche vor der Implementierung |
|
||
|
||
Zusätzlich (nicht explizit als Pflichtprüfung gefordert, aber Teil von
|
||
Akzeptanzkriterium 3 „lässt sich einzeln prüfen"): `TestForget_
|
||
KeepsOnlyRequestedSnapshotCount` — 3 Sicherungsläufe, `Forget(keepLast=1)`
|
||
reduziert auf genau 1 verbleibenden Snapshot.
|
||
|
||
## Korrektur an BAK-01 im selben Rutsch: Backup-Zielverzeichnis
|
||
|
||
Nutzerhinweis aufgegriffen: `NEXARCH_BACKUP_DIR` zeigte bei BAK-01
|
||
ursprünglich auf `/var/backups/nexarch` (Root-Dateisystem des LXC-
|
||
Containers, nicht auf einem der beiden dedizierten ZFS-Datasets). Korrigiert
|
||
auf `/var/nexarch-archiv/backups/postgres` (persistentes Dataset
|
||
`zfs/data/subvol-1131-disk-0`), NICHT `/var/nexarch-test/` (ephemeres
|
||
Dataset `ssd-rpool-data/swap/subvol-1131-disk-0`, wird von
|
||
`reset-test-env.sh`-Skripten anderer Module geleert). `objectbackup-cli`s
|
||
Repository liegt von Anfang an korrekt unter
|
||
`/var/nexarch-archiv/backups/objects`. Beide Pfade real auf
|
||
192.168.1.131 verifiziert (`df`/`mount` bestätigt ZFS-Dataset-Zuordnung),
|
||
BAK-01s Vollsicherung nach der Korrektur erneut über systemd ausgelöst und
|
||
bestätigt am neuen Ort gelandet.
|
||
|
||
ZFS-seitige Snapshot-/Replikations-Strategie für `nexarch/archiv` bleibt
|
||
bewusst außerhalb dieses Tickets (Infra-Runbook, siehe
|
||
`STORAGE-KONZEPT.md` Abschnitt 7 „Backup vs. Storage-Redundanz" sowie den
|
||
Hinweis, `zfs dedup=on` NICHT zu setzen — App-seitige Dedup über restic
|
||
genügt, ZFS-Dedup wäre auf dem 4-GB-Testhost ein Speicherrisiko).
|
||
|
||
## Echte Verdrahtung auf 192.168.1.131
|
||
|
||
- `objectbackup-cli` gebaut nach `/opt/nexarch-archive/bin/`
|
||
- `/etc/nexarch/archive-objectbackup.env` (0600)
|
||
- 3 systemd-Timer installiert und aktiviert: Sicherung stündlich (`:30`),
|
||
Vollständigkeitsprüfung wöchentlich (So. 04:00 UTC), Rotation täglich
|
||
(03:30 UTC) — `systemctl list-timers` bestätigt alle scharf
|
||
- Jeder der drei Dienste einmal über `systemctl start` ausgelöst, alle mit
|
||
`status=0/SUCCESS`; Journal bestätigt inhaltlich korrekte Ausgabe
|
||
|
||
## Build/Test-Ergebnis (192.168.1.131, `make check`)
|
||
|
||
```
|
||
go build ./... -> clean
|
||
go vet ./... -> clean
|
||
golangci-lint run ./... -> 0 issues
|
||
go test ./... -p 1 -count=1 -> 2/2 Pakete mit Tests ok (internal/backup, internal/objectbackup), 0 Fehlschläge
|
||
```
|
||
|
||
## Gesamtergebnis
|
||
|
||
**Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen
|
||
real gegen echtes restic-Tooling erfüllt. BAK-01-Pfadfehler im selben
|
||
Rutsch korrigiert und erneut end-to-end verifiziert.
|