RE:NODE

restic restore a check: jak získat data zpět z S3

Text: Tým RE:NODE
16 min čtení


Když chceš dostat data zpět z restic, najdi snapshot pomocí restic snapshots, nahlédni do něj přes restic ls a obnov ho do prázdného adresáře příkazem restic restore <id> --target /tmp/restore --include <path>. Jediný soubor nebo dump databáze vytáhneš rychleji přes restic dump a restic mount ti dovolí procházet všechny snapshoty jako složky, když ještě přesně nevíš, co hledáš. Příkaz restic check --read-data-subset předem prokáže, že data, která budeš potřebovat, jsou pořád čitelná. Nic z toho nefunguje bez hesla k repozitáři a nikdo - ani restic, ani poskytovatel úložiště - ti ho nevrátí, pokud je pryč.

Vytvoření repozitáře, záložní skript a retence jsou popsané v článku restic backups to S3. Tenhle článek je ta druhá polovina: den, kdy ta data potřebuješ, a nácviky, díky kterým je ten den nudný. Všude se předpokládá restic 0.17 nebo novější; kde je přepínač novější, nebo se starší verze chovají jinak, je to uvedeno.

Návrat do repozitáře#

Na serveru, který zálohy vytvářel, pořád funguje soubor s proměnnými prostředí z článku o nastavení: načti ho a každý příkaz níže poběží. Zajímavý je případ, kdy ten server už neexistuje a ty sedíš u čistého stroje jen s tím, co sis zapsal.

Potřebuješ přesně tři věci: umístění repozitáře (endpoint, bucket a prefix), dvojici přístupových klíčů s právem číst bucket a heslo k repozitáři. S tím obnoví data jakýkoli stroj s nainstalovaným restic.

/root/.restic-env
export AWS_ACCESS_KEY_ID=RNAKEXAMPLE123export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYexport AWS_DEFAULT_REGION=us-east-1export RESTIC_REPOSITORY=s3:https://s3.example.com/my-bucket/restic/web-01export RESTIC_PASSWORD_FILE=/root/.restic-password
bash
$ . /root/.restic-env$ restic cat config$ restic snapshots

restic cat config je nejmenší možný test: přečte jeden objekt a dešifruje ho. Pokud projde, endpoint, klíče i heslo jsou v pořádku a cokoli selže potom, je chyba v tom, co požaduješ, ne v přístupu. První příkaz na novém stroji je pomalejší než obvykle, protože restic sestavuje lokální cache metadat v ~/.cache/restic; to je normální a stane se to jen jednou.

Přístupové klíče jsou ta nahraditelná část. Pokud byly uložené jen na mrtvém serveru, vygeneruj v ovládacím panelu poskytovatele úložiště nový pár a pokračuj - repozitáři je jedno, kterým klíčem ho čteš. V úložišti RE:NODE S3 se klíče generují pro každý storage server zvlášť a zobrazují se v panelu, takže ztracený tajný klíč znamená jen cestu do panelu, ne katastrofu. Heslo je ta nenahraditelná část a má vlastní sekci o kus níž.

Pokud obnovuješ na jiném stroji, nastav --host výslovně, když myslíš ten původní. Nový stroj má jiný hostname a filtry, které ve výchozím stavu hledají „tento host“, nenajdou nic.

Jak najít správný snapshot#

Obnovit špatný snapshot se stává častěji než obnovit poškozený. Věnuj tomu tu minutu navíc.

bash
$ restic snapshots --host web-01 --tag nightly$ restic snapshots --latest 3 --compact$ restic snapshots --path /srv/minecraft

Filtry se kombinují: --host, --tag a --path zužují seznam a --latest n ukáže jen n nejnovějších snapshotů v každé skupině. Přepínač --json ti dá výstup, který můžeš poslat skriptu.

Slovo latest si zaslouží varování. Bez filtrů znamená latest nejnovější snapshot v celém repozitáři, ať obsahuje cokoli. Pokud tvůj noční skript zálohuje /srv a pak ukládá mysqldump přes --stdin-from-command, nejnovější snapshot je dump databáze a restic restore latest --target /tmp/restore ti místo serveru vrátí jeden soubor SQL. latest vždy k něčemu připni:

bash
$ restic restore latest --tag nightly --host web-01 --target /tmp/restore

Až budeš mít kandidáta, nahlédni dovnitř, než cokoli obnovíš:

bash
$ restic ls a81d0b37 /srv/minecraft/world$ restic ls --long latest --tag nightly /etc/nginx$ restic find --host web-01 'server.properties'$ restic diff 4f2a1c9e a81d0b37

Každý ze tří dělá jednu věc:

  • restic ls vypíše soubory jednoho snapshotu, případně omezené na jeden adresář. --long přidá velikost, oprávnění a čas změny, podle čehož poznáš, jestli je soubor ten před špatnou změnou, nebo po ní.
  • restic find prohledá všechny snapshoty podle jména nebo vzoru a řekne ti, které snapshoty ho obsahují. Je to nejrychlejší odpověď na otázku „kdy tenhle soubor naposledy existoval?“, když ho někdo smazal před třemi týdny.
  • restic diff porovná dva snapshoty a vypíše přidané (+), odebrané (-) a změněné (M) soubory. Když víš, že se něco rozbilo mezi úterkem a středou, rozdíl těch dvou snapshotů to obvykle ukáže.
PříkazOdpovídá na
restic snapshotsJaké zálohy existují, odkud a kdy
restic ls <id> <dir>Co je uvnitř jednoho snapshotu
restic find <pattern>Které snapshoty obsahují daný soubor
restic diff <a> <b>Co se změnilo mezi dvěma zálohami

restic restore podrobně#

restore je pracovní kůň. Přečte snapshot, stáhne jen balíky (packs), které potřebuje, a zapíše soubory včetně oprávnění, časových razítek a - při spuštění jako root - původního vlastníka. Spuštěné jako obyčejný uživatel patří obnovené soubory tomuto uživateli.

bash
# Whole snapshot into an empty directory$ restic restore a81d0b37 --target /tmp/restore# One directory$ restic restore a81d0b37 --target /tmp/restore --include /srv/minecraft/world# Everything except the noise$ restic restore a81d0b37 --target /tmp/restore \    --exclude /srv/minecraft/logs --exclude '*.tmp'# Contents of one directory, without the leading path$ restic restore a81d0b37:/srv/minecraft --target /tmp/mc

Cesty zůstávají tak, jak byly. Obnova /srv/minecraft/world do /tmp/restore vytvoří /tmp/restore/srv/minecraft/world, ne /tmp/restore/world - což překvapí lidi, kteří hledají své soubory přímo v kořeni cíle. Tvar snapshot:subfolder z posledního příkladu tu předponu odstraní: obnoví obsah /srv/minecraft přímo do /tmp/mc.

Volby include a exclude odpovídají těm při zálohování. --include a --exclude berou vzory, --iinclude a --iexclude nerozlišují velikost písmen a od restic 0.17 čtou --include-file a --exclude-file vzory ze souboru, jeden na řádek. Bez jakéhokoli --include se obnoví všechno.

Volby přidané v restic 0.17

Verze 0.17 udělala z restore mnohem užitečnější nástroj pro obnovu do adresáře, ve kterém už nějaká data jsou:

VolbaCo dělá
--dry-runUkáže, co by se obnovilo, nic nezapíše
--overwritealways (výchozí), if-changed, if-newer nebo never
--deleteOdstraní v cíli soubory, které ve snapshotu nejsou
--verifyPřečte obnovené soubory zpět a zkontroluje jejich obsah

--overwrite if-changed spolu s --delete promění restore v něco blízkého rsync ze snapshotu: nezměněné soubory zůstanou, změněné se přepíšou a přebytečné se odstraní, takže cíl skončí jako přesná kopie snapshotu. Je to nejrychlejší způsob, jak vrátit velký adresář, ve kterém se změnilo jen málo, a zároveň nejnebezpečnější příkaz v tomhle článku. Vždy ho nejdřív spusť s --dry-run -vv a přečti si seznam souborů, které by smazal.

--verify stojí druhé přečtení všeho obnoveného, ale z lokálního disku, ne ze sítě, a je to levná pojistka u obnovy, kterou se chystáš nasadit do produkce.

Jak dlouho to trvá

Rychlost obnovy je většinou rychlost stahování. restic stahuje balíky paralelně přes několik spojení (-o s3.connections=5 je výchozí hodnota pro S3; zvýšení může pomoci na rychlé lince a rychlém endpointu), dešifruje je a dekomprimuje a zapisuje soubory. Repozitář na vzdáleném endpointu přes domácí připojení je omezený tím připojením, ne restic. Změř si to jednou na skutečných datech, jak popisuje sekce o nácviku níže, místo abys to předpokládal.

restic dump: jeden soubor, jedna databáze, jeden archiv#

Když chceš jediný soubor, plná obnova je zbytečná. dump zapíše obsah jednoho souboru ze snapshotu na standardní výstup:

bash
$ restic dump a81d0b37 /etc/nginx/nginx.conf > /tmp/nginx.conf.old$ diff /tmp/nginx.conf.old /etc/nginx/nginx.conf

Je to přirozený způsob, jak obnovit dump databáze uložený přes --stdin-from-command, protože dump se nikdy nemusí dotknout disku:

bash
$ restic snapshots --tag mysql --latest 1$ restic dump --tag mysql latest /app.sql | mysql app_restore$ restic dump --tag postgres latest /app.sql | psql -d app_restore

Cesta je hodnota --stdin-filename, kterou jsi zadal při zálohování, a vidíš ji ve sloupci cest u snapshotu. Nejdřív obnov do nové, prázdné databáze (výše app_restore), porovnej ji s tím, co jsi čekal, a teprve pak na ni nasměruj aplikaci nebo prohoď názvy. Kroky specifické pro konkrétní databázi - uživatelé, oprávnění, --no-owner u dumpů Postgresu v custom formátu - jsou v článcích database backups and restores a mysqldump backup and restore.

Když dump dostane místo souboru adresář, vytvoří z něj archiv tar, nebo zip s --archive zip:

bash
$ restic dump latest --tag nightly /srv/minecraft/world > world.tar$ restic dump --archive zip latest --tag nightly /srv/minecraft/world > world.zip

To se hodí, když data musí skončit tam, kde restic není nainstalovaný - například archiv, který nahraješ přes správce souborů herního panelu nebo přes SFTP, kde server běží v kontejneru a žádný vlastní restic nemá.

restic mount: procházení všech snapshotů#

restic mount zpřístupní repozitář jako souborový systém jen pro čtení přes FUSE:

bash
$ mkdir -p /mnt/restic$ restic mount /mnt/resticNow serving the repository at /mnt/resticUse another terminal or tool to browse the contents of this folder.When finished, quit with Ctrl-c here or umount the mountpoint.

V druhém terminálu vypadá repozitář takto:

code
/mnt/restic/  ids/        one directory per snapshot ID  snapshots/  one directory per snapshot time, plus 'latest'  hosts/      snapshots grouped by host name  tags/       snapshots grouped by tag

Můžeš udělat cd do snapshots/2026-10-07T04:30:09+02:00/srv/minecraft, spustit ls, grep, less nebo diff -r proti živému stromu a jednotlivé soubory vykopírovat přes cp. Je to nejlepší nástroj, když ještě nevíš, co potřebuješ - „konfigurace z doby, než ji někdo upravil, někdy minulý týden“ - protože běžné nástroje fungují nad všemi snapshoty najednou.

Omezení:

  • Potřebuje FUSE: Linux, macOS s macFUSE nebo FreeBSD. Na Windows nefunguje a v kontejneru obvykle také ne, protože ten málokdy má /dev/fuse nebo oprávnění ho používat. Na Debianu a Ubuntu nainstaluj fuse3 (nebo fuse), pokud mount selže kvůli chybějícímu fusermount.
  • Vidí ho jen uživatel, který mount spustil, pokud nepřidáš --allow-other a systém to nepovolí v /etc/fuse.conf.
  • Hromadné kopírování je pomalé. Každé čtení stahuje a dešifruje balíky na požádání; cp -r adresáře o 20 GB z mountu je mnohem pomalejší než restic restore téhož adresáře, který si stahování plánuje. Procházej přes mount, obnovuj přes restore.

Ukonči ho Ctrl-C v terminálu, který ho spustil, nebo příkazem umount /mnt/restic (na některých systémech fusermount -u).

Kontrola repozitáře dřív, než ho budeš potřebovat#

restic check je způsob, jak zjistit, že je repozitář poškozený, v úterý odpoledne místo uprostřed výpadku. Má dvě úrovně.

bash
$ restic check$ restic check --read-data-subset=5%$ restic check --read-data-subset=3/12$ restic check --read-data

Prostý check ověřuje strukturu: že je index konzistentní, že strom každého snapshotu je úplný a že každý odkazovaný chunk existuje v nějakém balíku. Čte jen metadata a skončí rychle. Balíky neotevírá, takže nepozná balík, jehož bajty se rozpadly.

--read-data stáhne každý balík a ověří každý chunk proti jeho hashi. To je jediný úplný důkaz a u velkého repozitáře znamená celé stažení, s časem a odchozím provozem, který to obnáší. --read-data-subset čte jen část:

  • --read-data-subset=5% vybere při každém běhu náhodných 5 % balíků. Za mnoho běhů pokryje většinu repozitáře, ale bez záruky u konkrétního balíku.
  • --read-data-subset=n/t rozdělí balíky do t skupin a přečte skupinu n. Když spustíš 1/12 v lednu, 2/12 v únoru a tak dále, přečteš celý repozitář jednou za rok, každý balík přesně jednou.

Měsíční úloha v cronu s číslem měsíce jako n je rozumná výchozí volba pro repozitáře příliš velké na čtení vcelku:

bash
$ restic check --read-data-subset="$(date +%-m)/12"

Čistý běh končí hláškou no errors were found. Cokoli jiného stojí za to, abys se zastavil. check při chybách skončí nenulovým kódem, takže naplánovaný běh tě může upozornit stejnou cestou jako selhaná záloha - viz monitoring that tells you something.

Když check najde chyby

Nespouštěj prune ani forget na repozitáři, který check neprojde; poškození by se hůř posuzovalo. Postupuj popořadě:

  1. Spusť restic check znovu s čistou cache (--no-cache, nebo odsuň ~/.cache/restic stranou). Poškozená lokální cache může způsobit chyby, které repozitář nemá.
  2. Pokud je problém v indexu, restic repair index (restic 0.16 a novější; starší verze tomu říkají rebuild-index) ho znovu sestaví z balíků, které opravdu existují.
  3. Pokud balíky chybí nebo jsou poškozené, spusť novou zálohu ze zdroje, dokud zdroj ještě existuje. Chunky, které jsou pořád na disku, se nahrají znovu, což zahojí všechny snapshoty, které je sdílejí.
  4. Teprve potom zvaž restic repair snapshots, který přepíše snapshoty tak, aby zahodily odkazy na data, která jsou skutečně pryč. Ty soubory z historie ztratí; nevrátí je.

Poškození repozitáře na zdravém úložišti je vzácné. Když k němu dojde, příčina bývá mimo restic: úložiště, které tiše ztratilo objekty, pravidlo životního cyklu na bucketu, které smazalo staré soubory, nebo dva nástroje zapisující do stejného prefixu.

Realita ztraceného hesla#

Každý objekt v repozitáři restic je zašifrovaný hlavním klíčem a ten je uložený v adresáři keys/ zašifrovaný tvým heslem. Neexistuje zadní vrátka, odkaz na reset ani ticket u podpory, který by pomohl. Pokud jsou pryč všechna hesla k repozitáři, data jsou nenávratně ztracená - pro tebe, pro poskytovatele úložiště i pro vývojáře restic. To je návrh fungující tak, jak má.

Můžeš zařídit, aby se to nikdy nestalo:

bash
$ restic key list$ restic key add          # asks for a new password$ restic key passwd       # changes the password of the current key$ restic key remove 3e1b0c9d

Tři návyky, které to zajistí:

  • Měj víc než jeden klíč. restic key add přidá druhé heslo, které otevře stejný repozitář. Jedno drž na serveru v /root/.restic-password a druhé ve správci hesel nebo v zapečetěné obálce, která nežije společně se serverem. Každý klíč otevře všechno; jsou si rovnocenné.
  • Testuj kopii, ne jen originál. Heslo ve správci hesel s překlepem není záloha hesla. Otevři repozitář uloženou kopií jednou: restic -r ... --password-file /tmp/pw-from-vault snapshots.
  • Věz, co změna hesla nedělá. key passwd a key remove mění, kdo může odemknout hlavní klíč; data znovu nešifrují. Kdokoli, kdo kdysi měl funkční heslo a kopii souboru s klíčem, může repozitář pořád dešifrovat. Pokud heslo unikne, jediná skutečná oprava je nový repozitář: restic init čerstvého a restic copy snapshotů, které chceš, do něj.

Přístupové klíče a heslo jsou oddělená tajemství. Uniklý tajný klíč k S3 umožní někomu smazat nebo stáhnout tvé zašifrované balíky, ale ne je přečíst; změň ho v panelu poskytovatele. Uniklé heslo k repozitáři bez klíčů k S3 jim nic nepřinese, dokud se nedostanou i k bucketu. Ukládej ty dvě věci odděleně.

Nácvik obnovy s restic#

Záloha, kterou jsi nikdy neobnovil, je hypotéza. Obecná metoda - co měřit, co obvykle selhává, jak napsat runbook - je v článku testing a restore before you need it. Pro restic konkrétně je nácvik dost krátký, abys ho mohl spouštět každé čtvrtletí:

jen přihlašovací údajesnapshoty, restoreSprávce heselheslo, endpointPracovní strojrestic nainstalovánS3 bucketrepozitář restic/tmp/restorepracovní adresářOvěřenícanary, diff, start
Nácvik obnovy z čistého stroje
  1. Začni na stroji, který není tím serverem. Jednorázové VM, druhý malý server, tvůj notebook. Nainstaluj restic. Smyslem je dokázat, že umíš obnovit bez čehokoli z původního stroje.
  2. Použij jen to, co je uložené venku. Endpoint, bucket a prefix, přístupový klíč, heslo - ze správce hesel, ne zkopírované ze serveru. Pokud se kvůli něčemu potřebuješ podívat na server, zapiš si to: je to závislost tvé obnovy na věci, která selhala.
  3. Vyber starý snapshot. Ne latest: nejstarší snapshot, který je ještě v retenci, ověří, že retence fungovala a že stará data jsou pořád v pořádku.
  4. Obnovuj s puštěnými stopkami. time restic restore <id> --target /tmp/restore --verify. Zapiš si velikost a čas. Tohle číslo, vydělené velikostí tvého největšího serveru, je tvůj skutečný čas obnovy přes dané připojení.
  5. Obnov i databázi. restic dump ... | mysql app_restore nebo ekvivalent, pak spočítej řádky v tabulkách, na kterých záleží, a najdi nejnovější časové razítko.
  6. Ověř obsah. Hledej canary - soubor nebo řádek v databázi s datem zálohy - a porovnej pár klíčových souborů s jejich zdrojem přes diff. Pokud můžeš, spusť aplikaci nad obnovenými daty.
  7. Když už tam jsi, spusť kontrolu dat. restic check --read-data-subset=1/12 přidá k důkazům další dvanáctinu repozitáře.
  8. Zapiš, co chybělo. Konfigurační soubor mimo zálohované cesty, startovací přepínač, tajemství, které žilo jen v proměnné prostředí. Oprav zálohu, nejen runbook.

U herních serverů ten samý nácvik potvrdí, že se svět obnoví a načte; pravidla ukládání, která zajistí, že je svět vůbec konzistentní, jsou v článku game server backups to S3.

Chyby, na které při obnově narazíš#

Zpráva (výňatek)Příčina
wrong password or no key foundŠpatné heslo, nebo správné heslo k jinému repozitáři
Is there a repository at the following location?Špatný bucket, prefix nebo endpoint
repository is already lockedBěžící nebo spadlá záloha či prune drží zámek
no matching ID foundPřeklep v ID snapshotu, nebo filtr, který ho skrývá
SignatureDoesNotMatchŠpatný tajný klíč, nebo neshoda regionu či hodin

Poznámky ke každé z nich:

  • Špatné heslo. Zkontroluj, že RESTIC_PASSWORD_FILE ukazuje na soubor, na který si myslíš, a že soubor obsahuje heslo a nic jiného - žádnou mezeru na začátku, žádný druhý řádek. Od 0.17 restic při špatném hesle končí s kódem 12, který mohou skripty testovat.
  • Repozitář nenalezen. Prefix je součást adresy. s3:https://s3.example.com/my-bucket/restic/web-01 a .../my-bucket/restic/web01 jsou různé repozitáře a jeden z nich neexistuje. Vypiš obsah bucketu libovolným klientem S3 a uvidíš, co tam doopravdy je. Pokud endpoint vyžaduje adresování path-style, přidej -o s3.bucket-lookup=path, jak vysvětluje článek S3 path-style vs virtual-hosted.
  • Zamčeno. restore, ls, dump a mount berou neexkluzivní zámek a běží souběžně se zálohami, ale ne souběžně s prune. Pokud neběží žádný jiný proces, restic unlock odstraní zastaralé zámky bezpečně. Pro obnovu, která nesmí čekat, --no-lock přeskočí zamykání u příkazů jen pro čtení, s rizikem, že budeš číst, zatímco ti prune pod rukama maže data.
  • Chyby podpisu. Tajný klíč je špatný, nebo jsou hodiny stroje natolik pozadu, že je podpis požadavku odmítnut. Než budeš hledat cokoli jiného, oprav čas přes NTP.

FAQ#

Dá se obnovit záloha restic bez restic?

Ne. Repozitář je zašifrovaný, komprimovaný a rozdělený na chunky; nic jiného ho přečíst neumí. restic je jediný statický binární soubor pro Linux, macOS, Windows a BSD, takže odkaz na stažení měj v runbooku. Pokud potřebuješ obyčejný archiv pro něco, co restic spustit nemůže, vytvoř ho přes restic dump na stroji, který to umí.

Můžu na Windows obnovit zálohu z Linuxu?

Ano, restic restore funguje napříč operačními systémy. Unixový vlastník a některé bity oprávnění se na NTFS nepřenesou a mount na Windows není k dispozici, ale obsah souborů se vrátí neporušený.

Jak obnovit jen jeden smazaný soubor?

Najdi poslední snapshot, který ho měl, přes restic find --host web-01 'filename' a pak restic dump <id> /full/path/to/file > file. Tím se zapíše jen ten soubor a zbytek adresáře se nedotkne.

Přepíše restore novější soubory v cíli?

Ve výchozím stavu ano: --overwrite always nahradí existující soubory. Od restic 0.17 můžeš zvolit if-newer, aby se soubory novější než snapshot nechaly být, nebo never, aby se zapsaly jen chybějící. Obnova do prázdného adresáře se té otázce vyhne úplně.

Jak často spouštět check s read-data?

Prostý check týdně a rotující --read-data-subset=n/12 měsíčně přečtou každý balík jednou za rok, bez plného stahování pokaždé. U malého repozitáře je plný --read-data jednou za měsíc dost levný, aby se prostě dělal.

Stačí repozitář restic na jednom serveru S3?

Jako jedna kopie ano. Úložiště RE:NODE S3 například drží jednu kopii na NVMe na jednom místě, bez replikace - dobrá kopie mimo stroj, ne tvoje jediná. Zbytek pokryje restic copy do druhého repozitáře jinde, jak rozebírá článek S3 storage sizing and the 3-2-1 rule.