
Dlaczego warto tworzyć kopie zapasowe? Sprzęt jest bardzo i bardzo niezawodny, a do tego są "chmury", które pod względem niezawodności przewyższają fizyczne serwery: przy odpowiedniej konfiguracji serwer "chmurowy" bez trudu przetrwa awarię fizycznego serwera infrastrukturalnego, a z punktu widzenia użytkowników usług, wystąpi niewielki, ledwo zauważalny wzrost czasu obsługi. Ponadto, dublowanie informacji często wymaga opłacenia "dodatkowego" czasu procesora, obciążenia dysku oraz ruchu w sieci.
Idealny program działa szybko, nie wycieka z pamięci operacyjnej, nie ma dziur i w ogóle nie istnieje.
—Nieznany
Ponieważ programy wciąż są pisane przez programistów, a proces testowania często nie występuje, ponadto dostarczanie programów niezwykle rzadko odbywa się z zastosowaniem "najlepszych praktyk" (które same w sobie również są programami, a co za tym idzie, nieidealnymi), administratorzy systemów najczęściej muszą radzić sobie z zadaniami, które brzmią krótko, ale treściwie: „przywrócić, jak było”, „doprowadzić bazę do prawidłowego działania”, „działa wolno — przywracamy”, a także moje ulubione „nie wiem co, ale naprawić”.
Oprócz błędów logicznych, które pojawiają się w wyniku niedbałej pracy programistów, czy też zbiegu okoliczności, jak również niepełnej wiedzy lub nieznajomości drobnych szczegółów dotyczących budowy programów — w tym łącznie związkowych i systemowych, w tym systemów operacyjnych, sterowników i oprogramowania sprzętowego — istnieją także inne błędy. Na przykład większość programistów polega na środowisku uruchomieniowym, całkowicie zapominając o prawach fizyki, które wciąż nie mogą być obejdźone za pomocą programów. Chodzi tu o nieskończoną niezawodność podsystemu dyskowego i w ogóle jakiegokolwiek podsystemu przechowywania danych (w tym pamięci operacyjnej i pamięci podręcznej procesora!), i zerowy czas przetwarzania na procesorze, oraz brak błędów podczas transmisji w sieci i w trakcie przetwarzania na procesorze, oraz opóźnienia w sieci, które wynoszą 0. Nie można też lekceważyć słynnego terminu, ponieważ jeśli nie zdążysz na czas — będą problemy gorsze niż niuanse dotyczące działania sieci i dysku.

Co zrobić z problemami, które stają na drodze i wiszą nad cennymi danymi? Nie ma nic, co mogłoby zastąpić żywych programistów, a nie ma też pewności, że w najbliższym czasie będzie to możliwe. Z drugiej strony, jak dotąd, tylko kilka projektów udało się całkowicie udowodnić, że program działa zgodnie z zamysłem, a to, co udało się udowodnić, wcale niekoniecznie można zastosować do innych, podobnych projektów. Ponadto podobne dowody zajmują mnóstwo czasu i wymagają specjalnych umiejętności oraz wiedzy, co praktycznie minimalizuje ich zastosowanie, biorąc pod uwagę terminy. Poza tym, nadal nie mamy technologii do szybkiego, taniego i nieskończonego przechowywania, przetwarzania i przesyłania informacji. Takie technologie, jeśli w ogóle istnieją, zazwyczaj mają formę koncepcji lub — co najczęstsze — tylko w książkach i filmach fantastycznych.
Dobrzy artyści kopiują, wielcy artyści kradną.
—Pablo Picasso.
Najlepsze rozwiązania i zaskakująco proste rzeczy zwykle powstają tam, gdzie spotykają się na pierwszy rzut oka absolutnie niezgodne pojęcia, technologie, wiedza i dziedziny nauki.
Na przykład, ptaki i samoloty mają skrzydła, jednak mimo funkcjonalnego podobieństwa — zasada działania w pewnych trybach się zgadza, a problemy techniczne są rozwiązywane analogicznie: puste kości, użycie mocnych i lekkich materiałów itp. — wyniki są absolutnie różne, chociaż bardzo podobne. Najlepsze przykłady, które obserwujemy w naszej technice, także w dużej mierze są zapożyczone z przyrody: hermetyczne przedziały na statkach i łodziach podwodnych — to bezpośrednia analogia do pierścieniowych robaków; konstrukcja macierzy raid i weryfikacja integralności danych — duplikacja łańcucha DNA; a także parzyste narządy, niezależność działania różnych narządów od OUN (automatyzm pracy serca) i odruchy — autonomiczne systemy w Internecie. Oczywiście, branie i stosowanie gotowych rozwiązań „wprost” może rodzić problemy, ale kto wie, czy nie ma innych rozwiązań.
Gdyby tylko wiedzieć, gdzie upadniesz — podłożyłbym słomę!
—Białoruska ludowa przysłowia
Oznacza to, że kopie zapasowe są niezbędne tym, którzy pragną:
- Mieć możliwość przywrócenia działania swoich systemów przy minimalnych przestojach, a nawet całkowicie bez nich.
- Działaj śmiało, ponieważ w przypadku błędu zawsze istnieje możliwość przywrócenia.
- Minimalizować skutki celowego zniszczenia danych.
Tutaj — trochę teorii.
Każda klasyfikacja jest arbitralna. Natura nie klasyfikuje. Klasyfikujemy, ponieważ tak nam jest wygodniej, i klasyfikujemy według danych, które również przyjmujemy arbitralnie.
—Jean Bruhler
Niezależnie od fizycznego sposobu przechowywania, logiczne przechowywanie danych można umownie podzielić na dwa sposoby dostępu do tych danych: blokowy i plikowy. Takie podział w ostatnim czasie jest dość rozmyty, ponieważ nie istnieją czysto blokowe ani czysto plikowe, logiczne magazyny. Jednak dla uproszczenia przyjmujemy, że one istnieją.
Przechowywanie danych w blokach oznacza, że istnieje fizyczne urządzenie, na które zapisuje się dane w pewnych ustalonych porcjach, blokach. Dostęp do bloków odbywa się według pewnego adresu, każdy blok ma swój adres w obrębie urządzenia.
Kopia zapasowa zazwyczaj powstaje poprzez kopiowanie bloków danych. Aby zapewnić integralność danych w momencie kopiowania, wstrzymuje się zapis nowych bloków oraz zmiany istniejących. Jeśli wykorzystać analogię z codziennego życia — najlepiej pasuje szafka z identycznymi ponumerowanymi przegródkami.

Przechowywanie danych w plikach pod względem logicznego urządzenia jest bliskie blokowemu i często organizowane jest na jego szczycie. Ważne różnice to obecność hierarchii przechowywania i zrozumiałe dla ludzi nazwy. Powstaje abstrakcja w postaci pliku — nazwanej przestrzeni danych, oraz katalogu — specjalnego pliku, w którym przechowywane są opisy i dostęp do innych plików. Pliki mogą być wzbogacone o dodatkowe metadane: czas utworzenia, flagi dostępu itd. Zwykle rezerwuje się tak: znaleźć zmienione pliki, a następnie skopiować je do innego, strukturalnie identycznego magazynu plików. Integralność danych zwykle realizuje się przez brak plików, do których odbywa się zapis. Metadane plików zabezpiecza się analogicznie. Najbliższa analogia to biblioteka, w której są sekcje z różnymi książkami, a także istnieje katalog z zrozumiałymi nazwami książek.

Ostatnio czasami opisuje się jeszcze jeden wariant, od którego właściwie zaczęło się przechowywanie plików i który ma te same archaiczne cechy: przechowywanie obiektowe danych.
Różni się od przechowywania plików tym, że nie ma zagnieżdżenia większego niż jeden (płaska struktura), a nazwy plików, mimo że czytelne dla ludzi, są bardziej dostosowane do przetwarzania przez maszyny. Podczas tworzenia kopii zapasowych obiekty storage są najczęściej obsługiwane podobnie jak pliki, chociaż czasami istnieją też inne opcje.
— Są dwa rodzaje administratorów systemu: ci, którzy nie tworzą kopii zapasowych, i ci, którzy JUŻ je tworzą.
— W rzeczywistości są trzy typy: są także tacy, którzy sprawdzają, czy kopie zapasowe mogą być przywrócone.—Nieznany
Warto również zrozumieć, że sam proces tworzenia kopii zapasowych danych odbywa się za pomocą programów, dlatego ma wszystkie te same wady co inny program. Aby wyeliminować (nie wykluczyć!) zależność od czynnika ludzkiego oraz cech, które z osobna mogą nie mieć dużego wpływu, ale razem mogą dać zauważalny efekt, stosuje się tzw. zasadę 3-2-1. Istnieje wiele sposobów interpretacji, ale najbardziej podoba mi się następująca: należy przechowywać 3 zestawy tych samych danych, 2 zestawy powinny być przechowywane w różnych formatach, a 1 zestaw należy mieć w geograficznie oddzielnym magazynie.
Pod pojęciem formatu przechowywania należy rozumieć następujące:
- Jeśli występuje zależność od fizycznego sposobu przechowywania — zmieniamy fizyczny sposób.
- Jeśli występuje zależność od logicznego sposobu przechowywania — zmieniamy logiczny sposób.
Aby uzyskać maksymalny efekt zasady 3-2-1, zaleca się zmieniać format przechowywania obu sposobami.
Z punktu widzenia gotowości kopii zapasowej do jej bezpośredniego przeznaczenia — przywrócenia sprawności — wyróżnia się "gorące" i "zimne" kopie zapasowe. Gorące od zimnych różnią się tylko tym, że są od razu gotowe do użycia, podczas gdy zimne wymagają dodatkowych działań, aby je przywrócić: deszyfrowania, wydobywania z archiwum itd.
Nie należy mylić kopii gorących i zimnych z kopiami online i offline, które oznaczają fizyczną izolację danych i są w zasadzie innym rodzajem klasyfikacji metod tworzenia kopii zapasowych. Tak więc kopia offline — niepodłączona bezpośrednio do systemu, gdzie ma być przywrócona — może być zarówno gorąca, jak i zimna (w sensie gotowości do przywrócenia). Kopia online może być dostępna bezpośrednio tam, gdzie ma być przywrócona, a najczęściej jest gorąca, ale mogą zdarzyć się także kopie zimne.
Ponadto nie należy zapominać, że sam proces tworzenia kopii zapasowych zwykle nie kończy się na stworzeniu jednej kopii, a kopii może być dość dużo. W związku z tym należy różnicować pełne kopie zapasowe, tzn. te, które można przywrócić niezależnie od innych kopii zapasowych, a także kopie różnicowe (inkrementalne, różnicowe, dekremementalne itp.) — te, które nie mogą być przywrócone samodzielnie i wymagają wcześniejszego przywrócenia jednej lub kilku innych kopii zapasowych.
Kopie różnicowe inkrementalne mają na celu oszczędność miejsca na przechowywanie kopii zapasowych. W ten sposób do kopii zapasowej zapisane są tylko zmienione dane od ostatniej kopii zapasowej.
Kopie różnicowe dekremementalne tworzone są w tym samym celu, ale nieco inną metodą: wykonuje się pełną kopię zapasową, ale rzeczywiście przechowywana jest tylko różnica między nową kopią a poprzednią.
Osobno warto rozważyć proces tworzenia kopii zapasowej na przestrzeni, która wspiera brak przechowywania duplikatów. W ten sposób, jeśli zapisywane są pełne kopie zapasowe, rzeczywiście zapisana zostanie tylko różnica między kopiami zapasowymi, choć proces przywracania kopii zapasowych odbywa się w sposób analogiczny do przywracania z pełnej kopii i jest całkowicie przejrzysty.
Quis custodiet ipsos custodes?
(Kto ustali gardę? — łac.)
Bardzo nieprzyjemnie jest, gdy nie ma kopii zapasowych, jednak znacznie gorzej, gdy kopia zapasowa wydaje się być stworzona, ale przy przywracaniu okazuje się, że nie może być przywrócona, ponieważ:
- Integralność danych źródłowych została naruszona.
- Magazyn z kopiami zapasowymi jest uszkodzony.
- Odzyskiwanie danych przebiega dość wolno, nie można korzystać z danych, które zostały częściowo przywrócone.
Dobrze zaplanowany proces tworzenia kopii zapasowych musi uwzględniać takie uwagi, szczególnie dwie pierwsze.
Integralność danych źródłowych można zagwarantować na kilka sposobów. Najczęściej stosowane to: a) tworzenie migawków systemu plików na poziomie bloków, b) „zamrażanie” stanu systemu plików, c) specjalne urządzenie blokowe z przechowywaniem wersji, d) sekwencyjne zapisywanie plików lub bloków. Stosowane są również sumy kontrolne, aby zapewnić weryfikację danych podczas odzyskiwania.
Uszkodzenia magazynu danych również można wykryć za pomocą sum kontrolnych. Dodatkową metodą jest stosowanie specjalizowanych urządzeń lub systemów plików, w których nie można zmieniać już zapisanych danych, ale można dodawać nowe.
Aby przyspieszyć proces odzyskiwania, stosuje się odzyskiwanie danych z wieloma procesami — pod warunkiem, że nie ma "wąskiego gardła" w postaci wolnej sieci lub wolnego systemu dyskowego. Aby obejść problem z częściowo przywróconymi danymi, można podzielić proces tworzenia kopii zapasowych na relatywnie małe podzadania, z których każde wykonywane jest osobno. W ten sposób istnieje możliwość sekwencyjnego przywracania funkcjonalności z prognozowaniem czasu odzyskiwania. Problem ten najczęściej leży w sferze organizacyjnej (SLA), dlatego nie będziemy się na nim szczegółowo zatrzymywać.
Nie ten zna się na przyprawach, kto dodaje je do każdego dania, ale ten, kto nigdy nie doda do niego nic zbędnego.
—W. Siniawski
Praktyka dotycząca stosowanego oprogramowania przez administratorów systemów może się różnić, ale ogólne zasady i tak pozostają te same, w szczególności:
- Zaleca się stosowanie gotowych rozwiązań.
- Programy powinny działać w sposób przewidywalny, tzn. nie powinno być niedokumentowanych cech ani wąskich gardeł.
- Konfiguracja każdego programu powinna być na tyle prosta, aby nie było konieczności za każdym razem czytania instrukcji lub ściągi.
- Rozwiązanie powinno być uniwersalne, ponieważ serwery mogą różnić się parametrami sprzętowymi.
Oto kilka popularnych programów do tworzenia kopii zapasowych urządzeń blokowych:
- dd, znane weteranom administracji systemów, obejmuje również podobne programy (np. dd_rescue).
- Wbudowane w niektóre systemy plików programy obsługi (narzędzia), tworzące zrzut (dump) systemu plików.
- Uniwersalne narzędzia; na przykład partclone.
- Własne, często zamknięte rozwiązania; na przykład NortonGhost i jego późniejsze wersje.
Dla systemów plików problem kopii zapasowej jest częściowo rozwiązany za pomocą metod stosowanych dla urządzeń blokowych, jednak można to zrobić bardziej efektywnie, korzystając na przykład z:
- Rsync, uniwersalnego programu i protokołu do synchronizacji stanu systemów plików.
- Wbudowane narzędzia do archiwizacji (ZFS).
- Zewnętrzne narzędzia do archiwizacji; najpopularniejsze z nich to tar. Są też inne, na przykład dar — alternatywa dla tar, z myślą o nowoczesnych systemach.
Osobno warto wspomnieć o programowych narzędziach zapewniających spójność danych podczas tworzenia kopii zapasowych. Najczęściej stosowane są następujące warianty:
- Montowanie systemu plików w trybie tylko do odczytu (ReadOnly) lub zamrażanie systemu plików (freeze) — metoda, która ma ograniczone zastosowanie.
- Tworzenie zrzutów stanu systemów plików lub urządzeń blokowych (LVM, ZFS).
- Użycie zewnętrznych narzędzi do organizacji zrzutów, nawet w przypadkach, gdy wcześniejsze punkty nie mogą być spełnione z jakiegokolwiek powodu (programy typu hotcopy).
- Technika kopiowania przy zmianie (CopyOnWrite), jednak zazwyczaj jest ona powiązana z używaną FS (BTRFS, ZFS).
Tak więc, dla małego serwera trzeba zapewnić schemat tworzenia kopii zapasowych, odpowiadający następującym wymaganiom:
- Łatwy w obsłudze — nie wymaga szczególnych działań podczas pracy, minimalne działania dotyczące tworzenia i przywracania kopii.
- Uniwersalny — działający zarówno na dużych, jak i małych serwerach; jest to ważne w miarę wzrostu liczby serwerów lub skalowania.
- Instalowany przez menedżera pakietów lub za pomocą jednej–dwóch komend w stylu „pobrać i rozpakować”.
- Stabilny — używa standardowego lub od dawna ustalonego formatu przechowywania.
- Szybka w działaniu.
Kandydaci, którzy w miarę odpowiadają wymaganiom:
- rdiff-backup
- rsnapshot
- burp
- duplicati
- duplicity
- deja dup
- dar
- zbackup
- restic
- borgbackup

Jako testowe środowisko zastosowana zostanie maszyna wirtualna (oparta na XenServer) o następujących parametrach:
- 4 rdzenie 2.5 GHz,
- 16 GB pamięci RAM,
- 50 GB hybrid storage (macierz dyskowa z pamięcią podręczną SSD na poziomie 20% rozmiaru dysku wirtualnego) w postaci oddzielnego dysku wirtualnego bez partycji,
- 200 Mbit/s łącze do Internetu.
Jako serwer odbierający kopie zapasowe użyta zostanie praktycznie ta sama maszyna, tylko z twardym dyskiem o pojemności 500 GB.
System operacyjny — Centos 7 x64: standardowy podział, dodatkowa partycja będzie używana jako źródło danych.
Jako dane źródłowe weźmiemy stronę na WordPressie, z mediami o rozmiarze 40 GB, bazą danych na MySQL. Ponieważ serwery wirtualne mocno różnią się parametrami, a także dla lepszej powtarzalności, tutaj są
wyniki testowania serwera przy użyciu sysbench.sysbench —threads=4 —time=30 —cpu-max-prime=20000 cpu run
sysbench 1.1.0-18a9f86 (z użyciem załączonego LuaJIT 2.1.0-beta3)
Uruchamianie testu z następującymi opcjami:
Liczba wątków: 4
Inicjalizacja generatora liczb losowych z bieżącego czasu
Limit liczb pierwszych: 20000
Inicjalizacja wątków roboczych…
Wątki uruchomione!
Prędkość CPU:
zdarzeń na sekundę: 836.69
Wydajność:
zdarzeń/s (eps): 836.6908
czas trwania: 30.0039s
całkowita liczba zdarzeń: 25104
Opóźnienie (ms):
min: 2.38
avg: 4.78
max: 22.39
95. percentyl: 10.46
suma: 119923.64
Sprawiedliwość wątków:
zdarzeń (avg/stddev): 6276.0000/13.91
czas wykonania (avg/stddev): 29.9809/0.01
sysbench —threads=4 —time=30 —memory-block-size=1K —memory-scope=global —memory-total-size=100G —memory-oper=read memory run
sysbench 1.1.0-18a9f86 (z użyciem załączonego LuaJIT 2.1.0-beta3)
Uruchamianie testu z następującymi opcjami:
Liczba wątków: 4
Inicjalizacja generatora liczb losowych z bieżącego czasu
Uruchamianie testu prędkości pamięci z następującymi opcjami:
rozmiar bloku: 1KiB
całkowity rozmiar: 102400MiB
operacja: odczyt
zakres: globalny
Inicjalizacja wątków roboczych…
Wątki uruchomione!
Całkowita liczba operacji: 50900446 (1696677.10 na sekundę)
49707.47 MiB przesłanych (1656.91 MiB/s)
Wydajność:
zdarzeń/s (eps): 1696677.1017
czas trwania: 30.0001s
całkowita liczba zdarzeń: 50900446
Opóźnienie (ms):
min: 0.00
avg: 0.00
max: 24.01
95. percentyl: 0.00
suma: 39106.74
Sprawiedliwość wątków:
zdarzeń (avg/stddev): 12725111.5000/137775.15
czas wykonania (avg/stddev): 9.7767/0.10
sysbench —threads=4 —time=30 —memory-block-size=1K —memory-scope=global —memory-total-size=100G —memory-oper=write memory run
sysbench 1.1.0-18a9f86 (z użyciem załączonego LuaJIT 2.1.0-beta3)
Uruchamianie testu z następującymi opcjami:
Liczba wątków: 4
Inicjalizacja generatora liczb losowych z bieżącego czasu
Uruchamianie testu prędkości pamięci z następującymi opcjami:
rozmiar bloku: 1KiB
całkowity rozmiar: 102400MiB
operacja: zapis
zakres: globalny
Inicjalizacja wątków roboczych…
Wątki uruchomione!
Całkowita liczba operacji: 35910413 (1197008.62 na sekundę)
35068.76 MiB przesłanych (1168.95 MiB/s)
Wydajność:
zdarzeń/s (eps): 1197008.6179
czas trwania: 30.0001s
całkowita liczba zdarzeń: 35910413
Opóźnienie (ms):
min: 0.00
avg: 0.00
max: 16.90
95. percentyl: 0.00
suma: 43604.83
Sprawiedliwość wątków:
zdarzeń (avg/stddev): 8977603.2500/233905.84
czas wykonania (avg/stddev): 10.9012/0.41
sysbench —threads=4 —file-test-mode=rndrw —time=60 —file-block-size=4K —file-total-size=1G fileio run
sysbench 1.1.0-18a9f86 (z użyciem załączonego LuaJIT 2.1.0-beta3)
Uruchamianie testu z następującymi opcjami:
Liczba wątków: 4
Inicjalizacja generatora liczb losowych z bieżącego czasu
Dodatkowe flagi otwierania plików: (brak)
128 plików, po 8MiB każdy
Całkowity rozmiar plików: 1GiB
Rozmiar bloku: 4KiB
Liczba żądań I/O: 0
Stosunek odczytu/zapisu w teście I/O o losowym rozkładzie: 1.50
Okresowe FSYNC włączone, wywołując fsync() co 100 żądań.
Wywołując fsync() na końcu testu, włączone.
Używanie trybu I/O synchronicznego
Zarządzanie testem r/w o losowym dostępie
Inicjalizacja wątków roboczych…
Wątki uruchomione!
Wydajność:
odczyt: IOPS=3868.21 15.11 MiB/s (15.84 MB/s)
napisz: IOPS=2578.83 10.07 MiB/s (10.56 MB/s)
fsync: IOPS=8226.98
Opóźnienie (ms):
min: 0.00
średnio: 0.27
maks: 18.01
95. percentyl: 1.08
suma: 238469.45
Niniejsza notatka rozpoczyna dużą
serię artykułów o tworzeniu kopii zapasowych
- Kopie zapasowe, część 1: Po co są kopie zapasowe, przegląd metod, technologii
- Kopie zapasowe, część 2: Przegląd i testowanie narzędzi do tworzenia kopii zapasowych opartych na rsync
- Kopie zapasowe, część 3: Przegląd i testowanie duplicity, duplicaty, deja dup
- Kopia zapasowa, część 4: Przegląd i testowanie zbackup, restic, borgbackup
- Kopie zapasowe, część 5: Testowanie bacula i veeam backup for linux
- Kopie zapasowe, część 6: Porównanie narzędzi do tworzenia kopii zapasowych
- Kopie zapasowe, część 7: Wnioski
Źródło: habr.com
