Zálohy a obnova
Noční online záloha SQLite do OCI Object Storage, obnova jedním příkazem a nacvičená havárie.
Na této stránce
V jedné větě: Každou noc ve 02:30 UTC se udělá konzistentní snímek všech databází a klíčů, zabalí se a uloží do bucketu mimo VM; obnova je jeden příkaz
restore.sh latest.
Jak záloha funguje
sequenceDiagram
autonumber
participant T as systemd timer (02:30 UTC)
participant S as backup.sh
participant HC as healthchecks.io
participant P as backup.py (kontejner oci-cli)
participant V as volumes web-data, inventory-data
participant B as bucket minishop-backups
T->>S: spustit (uživatel deploy)
S->>HC: /start
S->>P: docker run … backup
P->>V: online backup SQLite (ordering, journeys, users, inventory) + /data/keys + obrázky produktů
P->>P: integrity_check, tar.gz minishop-RRRRMMDDTHHMMSSZ
P->>B: upload (přihlášení instance principal – bez klíče)
S->>HC: ping OK (jinak /fail)
Note over B: lifecycle pravidlo smaže zálohy starší než 7 dní
| Část | Kód |
|---|---|
| Časovač a služba systemd | minishop-backup.timer, minishop-backup.service |
| Spouštěč + hlášení na healthchecks.io | backup.sh |
| Vlastní záloha a obnova (Python) | backup.py |
| Obnova | restore.sh |
| Bucket, lifecycle, oprávnění | backup.tf |
Rozhodnutí a proč
| Rozhodnutí | Proč |
|---|---|
| Online backup API SQLite, ne kopie souboru | soubor může být uprostřed zápisu – kopie by byla poškozená; .backup udělá konzistentní snímek za běhu |
| Instance principal (identita VM) | na VM neleží žádný klíč ani heslo k úložišti |
| VM smí zapisovat a číst, ne mazat ani přepsat | napadená VM zálohy nezničí; staré maže lifecycle pravidlo služby Object Storage |
Bucket mimo VM, prevent_destroy |
záloha musí přežít smazání VM i omyl v OpenTofu |
Zálohuje se i /data/keys |
bez Data Protection klíčů by po obnově neplatily otevřené formuláře |
Zálohují se i obrázky produktů (/data/images skladu, e-shop krok 2B) |
jména souborů jsou v inventory.db – bez souborů by výloha ukazovala chybějící obrázky. Složky se zálohují jako celek (DIRECTORIES v backup.py); starší záloha bez nich obnovu nezastaví |
| RabbitMQ se nezálohuje | zprávy jsou dočasné; pravda je v outboxech obnovených databází |
| healthchecks.io (dead man's switch) | ozve se, když záloha neproběhne – to zevnitř VM nikdo nepozná |
Image oci-cli připnutý na verzi |
záloha se nesmí rozbít tím, že se změní nástroj |
Obnova
sudo -u deploy /opt/minishop/restore.sh list # co je v bucketu
sudo -u deploy /opt/minishop/restore.sh latest # nejnovější záloha
Skript zastaví web a inventory-api (nikdo nezapisuje), stáhne zálohu, zkontroluje ji (integrity_check),
vymění soubory ve volumes (původní nechá jako *.before-restore-…) a služby znovu spustí.
Po startu služby doplní obnoveným databázím chybějící migrace schématu (Sdílené jádro – migrace databází) – i záloze z doby před migracemi (baseline). Obnovit jde tedy i starší zálohu; opačně ne – kód starší než schéma zálohy novější sloupce jen ignoruje.
Před rizikovou akcí ruční záloha: sudo systemctl start minishop-backup.
Nová databáze = přidat do DATABASES, nová složka s daty (jako obrázky) do DIRECTORIES v backup.py.
Cvičná havárie
Obnova, kterou nikdo nezkusil, je jen přání. Proto proběhla zkouška: VM se smazala → tofu apply vytvořila novou →
workflow Deploy nasadil aplikaci → restore.sh latest vrátil data → objednávky byly zpět.