Ein Restore ist der eine Moment, in dem man garantiert unter Stress steht: irgendwas ist kaputt, und ausgerechnet jetzt soll man sich die Reihenfolge aus Flux-suspend, PVC-leeren, restic restore und Flux-resume fehlerfrei aus dem Kopf klicken. Genau diese Reihenfolge gehört nicht in den Kopf, sondern in Code. Im go-task-Setup des Labs übernimmt das die backup-Kategorie — ein dünner Wrapper um
VolSync
und
restic
, der aus dem VolSync-Aufbau ein paar einprägsame Kommandos macht.
Drei Befehle für den Alltag
Der harmlose Teil zuerst. Snapshots ansehen:
task backup:list APP=snac NS=fediverse-system
Das startet einen ephemeren Job (restic:0.18.1 snapshots, der das ${APP}-volsync-secret als envFrom zieht), wartet auf dessen Abschluss, gibt die Logs aus und räumt sich selbst wieder weg. Einen Snapshot sofort erzwingen — etwa direkt vor einem riskanten Upgrade:
task backup:snapshot APP=snac NS=fediverse-system
Hier wird die ReplicationSource mit trigger.manual=<timestamp> gepatcht und auf den volsync-src-<app>-Job gewartet. Beide Tasks brauchen nur APP (und einen KUBE_CONTEXT); NS defaultet auf default, und ob die App ein Deployment oder ein StatefulSet ist, ermittelt der Task selbst.
Der gefährliche Teil: restore
Ein Restore ist kein einzelner Aufruf, sondern eine Kette — und jede Stufe kann man von Hand vergessen oder vertauschen:
task backup:restore APP=snac NS=fediverse-system PREV=2
│
├─ _label ns → pod-security: privileged (nur falls nicht ohnehin privileged)
├─ _suspend flux suspend ks/snac + scale deploy|sts → 0 (auf Pod-Delete warten)
├─ _wipe Job (busybox, privileged): cd /data && find . -delete
├─ _restore ReplicationDestination → restic (copyMethod: Direct, previous: 2)
├─ _resume flux resume ks/snac
└─ _unlabel ns → pod-security zurücksetzen
Der Clou steckt darin, dass der Task die Parameter des Restores nicht erfindet, sondern aus der vorhandenen ReplicationSource ausliest: den Quell-PVC (CLAIM) und die moverSecurityContext-UID/GID. So schreibt der Restore-Mover mit exakt der uid:gid der App zurück in genau die Live-PVC, an der die App später wieder hochkommt. PREV steuert, wie viele Snapshots zurück restauriert wird (0 = neuester) — direkt durchgereicht an previous im ReplicationDestination:
kind: ReplicationDestination
spec:
trigger: { manual: restore-once }
restic:
repository: "${APP}-volsync-secret"
destinationPVC: "$CLAIM"
copyMethod: Direct # schreibt direkt in die Live-PVC
previous: $PREV
Weil copyMethod: Direct direkt auf das Live-Volume schreibt, ist die Reihenfolge nicht optional: erst die App stoppen (_suspend), dann das Volume leeren (_wipe), dann restaurieren. Würde man bei laufender App restaurieren, kämpften App und Mover um dieselben Dateien.
Der Pod-Security-Trick
Der wipe-Job ist bewusst brachial — eine busybox, die find . -delete auf dem gemounteten PVC ausführt, und dafür privileged: true braucht:
command: ["/bin/sh", "-c", "cd /data; find . -delete"]
securityContext:
privileged: true
In einem Namespace mit strikten
Pod Security Standards
würde dieser Pod schlicht nicht zugelassen. Deshalb labelt _label den Namespace temporär auf pod-security.kubernetes.io/enforce=privileged — aber nur, wenn er nicht ohnehin schon privileged ist (sonst bliebe das Label nach dem _unlabel fälschlich hängen). Nach erfolgreichem Restore setzt _unlabel die ursprüngliche Posture wieder. Das ist die operative Kehrseite der privileged-movers-Notiz aus dem VolSync-Artikel: Mover und wipe-Job brauchen kurz mehr Rechte, als die App selbst je bekommen darf.
Wenn das Repo klemmt: unlock
Stirbt ein Mover mitten im Lauf, hinterlässt restic ein stehengebliebenes Lock — und jeder folgende Snapshot oder Restore hängt. Dafür gibt es den Notnagel:
task backup:unlock APP=snac NS=fediverse-system
Ein Job mit restic unlock --remove-all, mehr nicht. Aber genau die Art Einzeiler, an die man sich um drei Uhr nachts nicht erinnert.
Kein Hexenwerk — und genau das ist der Punkt. Der Unterschied zwischen „ich tippe sechs kubectl- und flux-Kommandos in der richtigen Reihenfolge" und „ich tippe task backup:restore" ist im Ernstfall der Unterschied, der zählt. Eine Restore-Prozedur, die man nicht regelmäßig übt, ist im Zweifel keine — als Task ist sie wenigstens reproduzierbar.
