Záloha, kterou jste nikdy neobnovili, je hypotéza, nikoli záchranná síť. U malé aplikace běžící na PostgreSQL s Docker volumes se rozdíl mezi větou „zálohy děláme“ a větou „službu dokážeme znovu spustit“ obvykle ukáže v tu nejhorší chvíli. Tento článek popisuje test obnovy (restore drill), který zvládnete na notebooku nebo záložním virtuálním stroji, vysvětluje rozhodnutí, na nichž stojí, a otevřeně říká, co takový test prokázat nedokáže. Záměrně je úzký: jedna databáze, jedna aplikace, Docker volumes a žádný cloudový provozní model.
Nejdřív pojmenujte, z čeho se zotavujete
Test potřebuje scénář, jinak neověřuje nic konkrétního. Pro malý stack pokrývají většinu reálných ztrát tři situace:
- Ztracený nebo poškozený volume. Selže disk hostitele, někdo volume omylem smaže, nebo špatná migrace poškodí data a vy chcete vrátit předchozí stav.
- Ztracený hostitel. Celý stroj je pryč a musíte službu postavit znovu ze záloh a ze své konfigurace Compose.
- Logická chyba. Někdo spustil destruktivní příkaz proti produkční databázi. Databáze je zdravá, ale data jsou špatně.
To, které z těchto situací přežijete, určuje zvolená metoda zálohování. Dokumentace PostgreSQL popisuje tři zásadně odlišné přístupy k zálohování dat: SQL dump, zálohu na úrovni souborového systému a průběžné archivování, každý s vlastními silnými a slabými stranami (https://www.postgresql.org/docs/17/backup.html). Dokumentace zdůrazňuje, že postup je v principu jednoduchý, ale je třeba jasně rozumět použitým technikám a předpokladům. Test obnovy je způsob, jak tyto předpoklady ověřit na vlastním nasazení.
Předem si prostými slovy zapište dva cíle: kolik čerstvých dat byste byli ochotni ztratit a jak dlouho smí být služba nedostupná. Zdroje pro tyto hodnoty žádná čísla nedávají a tento článek také ne. Jsou to obchodní rozhodnutí. Úkolem testu je změřit, co vaše současné nastavení skutečně poskytuje, abyste to mohli porovnat s tím, co chcete.
Zvolte metodu zálohy, kterou bude test procvičovat
U malé aplikace se reálná volba obvykle odehrává mezi logickým dumpem pomocí pg_dump a pokročilejším nastavením průběžného archivování. Test by měl ověřovat tu metodu, kterou skutečně používáte.
Logické dumpy pomocí pg_dump. Podle referenční dokumentace pg_dump vytváří konzistentní zálohy i tehdy, když je databáze souběžně používána, a neblokuje ostatní uživatele, čtenáře ani zapisovatele (https://www.postgresql.org/docs/17/app-pgdump.html). Díky tomu je praktický pro malý živý systém. Má však omezení, která je dobré znát:
- Dumpuje jedinou databázi. Role a tablespaces jsou globální objekty sdílené v rámci clusteru a dokumentace odkazuje na pg_dumpall pro jejich zálohu nebo pro zálohu celého clusteru. Pokud vaše aplikace závisí na konkrétních rolích a vy dumpujete jen jednu databázi, může obnova na čistém serveru selhat na vlastnictví objektů nebo oprávněních. Je to jedno z nejčastějších překvapení, která test odhalí.
- Výstup existuje ve formátech skriptu a archivu. Textové skripty se obnovují předáním do psql; archivní formáty je nutné obnovovat pomocí pg_restore.
- Formáty custom (-Fc) a directory (-Fd) jsou nejflexibilnější: umožňují vybírat a přeskupovat archivované položky, podporují paralelní obnovu a jsou ve výchozím stavu komprimované. Formát directory je jediný, který podporuje paralelní dump.
Pro test je obvykle lepší volbou formát custom nebo directory, protože pg_restore umožňuje archiv prozkoumat a vybrat, co obnovit, což se hodí, když chcete nejdřív ověřit jen několik tabulek.
Průběžné archivování a obnova k časovému okamžiku. Osnova kapitoly v dokumentaci řadí k tomuto přístupu archivaci WAL, základní zálohy, obnovu z průběžného archivu a časové větve (timelines) (https://www.postgresql.org/docs/17/backup.html). Je to cesta k obnově do okamžiku těsně před logickou chybou, ale je to také více mechaniky, kterou je třeba nastavit a hlavně otestovat. Pokud tuto metodu používáte, musí váš test zahrnovat skutečné provedení obnovy, nikoli jen ověření, že se archivní soubory hromadí.
Záloha na úrovni souborového systému. Kopírování souborů volume svádí zejména v prostředí Dockeru a patří mezi tři přístupy, které dokumentace uvádí. Kompromis spočívá v tom, že si musíte být jisti, že kopie je ve stavu, ze kterého se PostgreSQL dokáže zotavit. Než se spolehnete na surovou kopii živého datového adresáře, přečtěte si v dokumentaci část o záloze na úrovni souborového systému a nechte test prokázat, že to funguje, místo abyste to předpokládali.
Postavte scratch prostředí, které se nemůže dotknout produkce
Nejdůležitějším návrhovým pravidlem testu obnovy je izolace. Chcete mít jistotu, že překlep nemůže namířit obnovu na živou databázi.
Praktická opatření:
- Použijte samostatný název projektu Compose, aby se nekolidovaly názvy kontejnerů, sítí a volumes s produkcí. Docker volumes jsou mechanismus úložiště, který dokumentace Dockeru popisuje pro uchování dat kontejnerů (https://docs.docker.com/engine/storage/volumes/); scratch projekt by měl dostat vlastní, nově vytvořené volumes, nikoli znovu používat nebo připojovat ten produkční.
- Nepublikujte scratch databázi na stejném portu hostitele jako produkci. Ještě lepší je nepublikovat žádný port a ověřovací příkazy spouštět uvnitř sítě kontejnerů.
- Ve scratch konfiguraci použijte zřetelně odlišné přihlašovací údaje a jiný název hostitele databáze, aby chybně namířené spojení selhalo hlasitě.
- Test spouštějte ze stroje nebo od uživatele, který nemá v prostředí produkční přihlašovací údaje. Dokumentace pg_dump uvádí, že výchozí hodnoty připojení mohou pocházet z proměnných prostředí, například PGDATABASE, což připomíná, že okolní nastavení prostředí může cíl vybrat potichu za vás.
Pokud produkce používá konkrétní tag image PostgreSQL, použijte stejný tag i v testu. Obnova do jiné hlavní verze je jiný test (test upgradu) a jejich míchání ztěžuje interpretaci selhání.
Projděte test krok za krokem
Následuje postup pro cestu přes pg_dump. Příkazy přizpůsobte svému souboru Compose; důležitější než přesná syntaxe je struktura.
1. Získejte zálohu tak, jak byste to udělali při skutečném incidentu. Neberte ji z lokálního adresáře produkčního hostitele, pokud je váš skutečný plán získat ji z jiného stroje nebo úložiště. Pokud získání vyžaduje přihlašovací údaje nebo člověka, který je na dovolené, právě jste našli způsob selhání. 2. Spusťte prázdný scratch kontejner PostgreSQL s novým, prázdným volume. 3. Vytvořte role, které aplikace očekává, před obnovou, nebo obnovte globální objekty, pokud jste je zachytili pomocí pg_dumpall. 4. Obnovte data. U textového dumpu předejte skript do psql. U archivů custom nebo directory použijte pg_restore. Obě cesty popisuje dokumentace pg_dump. Čtěte výstup, nekontrolujte jen návratový kód: u archivních formátů dokumentace uvádí, že byste měli výstup zkontrolovat kvůli varováním, a chyby obnovy chybějících objektů lze v rolujícím textu snadno přehlédnout. 5. Archiv prozkoumejte dřív, než mu uvěříte. Dokumentace uvádí, že dumpy v jiném než textovém formátu lze prozkoumat pomocí volby --file programu pg_restore, která místo provedení zapíše SQL. Je to také bezpečnostní opatření: dokumentace varuje, že obnova dumpu způsobí, že cíl provede libovolný kód zvolený superuživateli zdroje, a že částečná obnova toto riziko neomezuje. U vlastních záloh z vlastního serveru je to riziko nízké, ale pokud záloha mohla projít nedůvěryhodnýma rukama, nejdřív ji prozkoumejte. 6. Změřte obnovu od začátku do konce, včetně získání zálohy a nastavení rolí. Zaznamenejte číslo. Je to vaše naměřená základní hodnota, nikoli odhad. 7. Spusťte aplikaci proti scratch databázi a vyzkoušejte ji, místo abyste skončili u věty „databáze naběhla“.
Ověřte, že obnovená data jsou skutečně použitelná
Obnova, která doběhne bez chyb, může přesto vyprodukovat nepoužitelný systém. Ověření by mělo mít několik vrstev.
Strukturální kontroly. Porovnejte seznam tabulek, indexů a rozšíření s produkcí. Dokumentace pg_dump obsahuje upozornění ohledně rozšíření: při dumpu vybraných rozšíření není zaručeno, že se výsledek sám o sobě obnoví do čisté databáze, protože závislosti nejsou automaticky zahrnuty. I u plného dumpu ověřte, že rozšíření, která aplikace potřebuje, jsou v image, do něhož obnovujete, k dispozici.
Kontroly obsahu. Vyberte několik tabulek a porovnejte počty řádků nebo časové značky nejnovějších záznamů s tím, co očekáváte. Smyslem je potvrdit, že záloha je tak čerstvá, jak věříte. Noční úloha, která týdny tiše selhává, bude vypadat v pořádku, dokud se nepodíváte na nejnovější řádek.
Large objects a sekvence. Pokud aplikace ukládá large objects, dokumentace pg_dump uvádí, že jsou ve výchozím stavu zahrnuty, s výjimkou případů, kdy jsou zadány volby jako --schema, --table nebo --schema-only. Pokud někdo později zúžil příkaz dumpu filtrem tabulek, large objects mohly nenápadně vypadnout. Podobně se hodnoty sekvencí dumpují spolu s daty; zkontrolujte, že nové vložení po obnově nekoliduje s existujícími klíči.
Kontroly na úrovni aplikace. Přihlaste se, vytvořte záznam, načtěte ho zpět, spusťte nástroj pro migrace v režimu dry-run nebo status. Tím se zachytí nesoulad mezi obnoveným schématem a verzí aplikace ve vašem repozitáři.
Způsoby selhání, které takový test typicky odhalí
Jde o vzory, na které se zaměřit. Jsou to pomůcky pro uvažování, nikoli tvrzení o konkrétním incidentu.
- Zálohy, které existují, ale nelze je získat, protože leží jen na hostiteli, který selhal.
- Chybějící globální objekty. Dump databáze se obnoví, ale role, hesla nebo tablespaces chybí, protože pg_dump pokrývá jednu databázi a pg_dumpall objekty celého clusteru.
- Špatný nástroj pro formát. Pokus předat archivní soubor do psql nebo očekávání, že pg_restore přečte textový skript.
- Tiché částečné dumpy. Volby omezující rozsah dumpu, které vytvoří soubor vypadající normálně, ale vynechávající data.
- Rozdíl verzí. Scratch image se liší od produkce, nebo aplikační kód očekává novější schéma, než obsahuje záloha.
- Netestovaný postup obnovy při průběžném archivování. Archivní soubory se hromadí měsíce, ale nikdo neprovedl obnovu ani nepochopil časové větve, takže první pokus nastane během výpadku.
- Předpoklady o Docker volumes. Víra, že data v pojmenovaném volume jsou automaticky zálohována. Volume je trvalé úložiště na hostiteli, nikoli jeho kopie jinde.
Realistický kontrolní seznam
Použijte ho jako výchozí šablonu a upravte podle sebe.
Před testem: - Písemný scénář a cíle ohledně ztráty dat a výpadku, kterých chcete dosáhnout. - Scratch projekt Compose s odlišným názvem, volumes a přihlašovacími údaji a bez sdílených portů. - Stejný tag image PostgreSQL jako v produkci.
Během testu: - Záloha získána stejnou cestou, jakou by šla skutečná obnova. - Role a globální objekty řešeny explicitně. - Výstup obnovy přečten celý, varování zaznamenána. - Celkový uplynulý čas zaznamenán. - Strukturální kontroly, kontroly obsahu a kontroly aplikace dokončeny.
Po testu: - Každé překvapení zapsáno s vlastníkem a nápravou. - Příkazy pro zálohu a obnovu v runbooku aktualizovány přesně tak, jak byly spuštěny. - Stanoveno datum dalšího testu, který se spouští také při změnách, jako je upgrade PostgreSQL, nové rozšíření nebo změna nástrojů pro zálohování.
Co test neprokáže
Buďte poctiví ohledně hranic. Test na malém souboru dat vypovídá jen málo o době obnovy velkého; kapitola PostgreSQL obsahuje část o práci s velkými databázemi z dobrého důvodu. Scratch obnova také nemůže prokázat, že disk, síť nebo oprávnění produkčního hostitele se budou za skutečné zátěže chovat stejně. Úspěšný test ukazuje, že tato záloha se v tento den s těmito kroky obnovila. Nezaručuje, že zítřejší záloha bude dobrá, a proto má kontrola čerstvosti obsahu a pravidelný rozvrh větší váhu než kterýkoli jednotlivý běh.
Tento článek vychází pouze z dokumentace PostgreSQL k zálohování a k pg_dump a z dokumentace Dockeru k volumes. Nepokrývá šifrování záloh, politiku uchovávání, spravované databázové služby ani požadavky souladu s předpisy a poskytnuté zdroje v těchto oblastech konkrétní tvrzení nepodporují. Postup berte jako rámec k přizpůsobení a každý příkaz ověřte v dokumentaci pro své přesné verze PostgreSQL a Dockeru.
Udělejte z testu rutinu
Hodnota testu obnovy se zvyšuje, když je nudný. Scratch prostředí naskriptujte tak, aby test byl jediný příkaz, runbook udržujte ve stejném repozitáři jako soubor Compose a test opakujte vždy, když se na datové vrstvě něco změní. První test téměř jistě něco najde. A právě o to jde: chcete to najít v klidné odpoledne, a ne během incidentu.