Cześć, Habr!
Dziś chcę opowiedzieć o naszym doświadczeniu w automatyzacji tworzenia kopii zapasowych dużych zasobów danych w Nextcloud w różnych konfiguracjach. Pracuję jako CTO w „Molnia AK”, gdzie zajmujemy się zarządzaniem konfiguracją systemów IT, a do przechowywania danych używamy Nextcloud. W tym również z rozproszoną strukturą i z rezerwacją.
Problemy wynikające z charakterystyki instalacji polegają na tym, że danych jest dużo. Wersjonowanie, które oferuje Nextcloud, rezerwacja, subiektywne przyczyny i inne czynniki tworzą wiele duplikatów.
Tło
Podczas administracji Nextcloud pojawia się problem organizacji efektywnej kopii zapasowej, którą należy obowiązkowo szyfrować, ponieważ dane są cenne.
Oferujemy warianty przechowywania kopii zapasowej u nas lub u klienta na jego oddzielnych maszynach od Nextcloud, co wymaga elastycznego zautomatyzowanego podejścia do administracji.
Mamy wielu klientów, wszyscy mają różne konfiguracje, a także są na swoich lokalizacjach z własnymi szczegółami. Standardowa metoda, w której cała lokalizacja należy do Ciebie, i kopie zapasowe są tworzone na podstawie crona, słabo pasuje.
Na początek spójrzmy na dane wejściowe. Potrzebujemy:
- Skalowalności w przypadku jednej węzła lub kilku. Dla dużych instalacji używamy minio jako magazynu.
- Zidentyfikować problemy z realizacją kopii zapasowych.
- Musimy przechowywać kopie zapasowe u klientów i/lub u nas.
- Szybkie i łatwe rozwiązywanie problemów.
- Klienci i instalacje znacznie różnią się od siebie — trudno osiągnąć jednorodność.
- Czas przywracania powinien być minimalny w dwóch scenariuszach: pełne przywrócenie (katastrofa) i jedna folder — usunięty przez pomyłkę.
- Funkcja deduplikacji jest obowiązkowa.

Do rozwiązania problemu zarządzania kopiami zapasowymi podłączyliśmy GitLab. Więcej szczegółów w podsumowaniu.
Oczywiście nie jesteśmy pierwszymi, którzy rozwiązują podobne zadanie, ale wydaje nam się, że nasze praktyczne doświadczenie może być interesujące i jesteśmy gotowi się nim podzielić.
Ponieważ w naszej firmie przyjęto politykę open source, szukaliśmy rozwiązania z otwartym kodem źródłowym. Z naszej strony dzielimy się swoimi rozwinięciami i publikujemy je. Na przykład, na GitHubie znajduje się , który instalujemy u klientów, wzmacniający bezpieczeństwo danych na wypadek przypadkowego lub zamierzonego usunięcia.
Narzędzia do tworzenia kopii zapasowych
Rozpoczęliśmy poszukiwania metod rozwiązania od wyboru narzędzia do tworzenia kopii zapasowych.
Tradycyjny tar + gzip działa słabo — dane się powtarzają. Inkremet często zawiera bardzo mało zmian w rzeczywistości, a większość danych w jednym pliku się powtarza.
Jest jeszcze jeden problem — nadmiarowość rozproszonego magazynu danych. Używamy minio, a jego dane generalnie są nadmiarowe. Musielibyśmy robić kopię zapasową za pomocą samego minio — obciążając je i korzystając ze wszystkich połączeń między systemem plików, a co nie mniej ważne, istnieje ryzyko zapomnienia o części wiader i metainformacji. Albo użyć deduplikacji.
Narzędzia do tworzenia kopii zapasowych z deduplikacją są dostępne w open source (na habrze były ) i naszymi finalistami zostały i . O naszym porównaniu dwóch aplikacji poniżej, a teraz opowiemy, jak zorganizowaliśmy cały schemat.
Zarządzanie tworzeniem kopii zapasowych
Borg i Restic są dobre, ale żaden z tych produktów nie ma scentralizowanego mechanizmu zarządzania. Do zarządzania i kontroli wybraliśmy narzędzie, które i tak mamy wdrożone, bez którego nie wyobrażamy sobie naszej pracy, w tym automatyzacji — to znany CI/CD – GitLab.
Pomysł jest następujący: na każdą węzeł przechowujący dane Nextcloud instalujemy gitlab-runner. Runner uruchamia zgodnie z harmonogramem skrypt monitorujący proces tworzenia kopii zapasowych, który uruchamia Borg lub Restic.
Co osiągnęliśmy? Informację zwrotną z wykonania, wygodną kontrolę zmian, szczegóły w przypadku błędu.
Oto opublikowaliśmy przykłady skryptu do różnych zadań, a my ostatecznie przyłączyliśmy go do kopii zapasowej nie tylko Nextcloud, ale i wielu innych usług. Tam jest również planista, jeśli nie chce się go ręcznie konfigurować (a nam się nie chce) i .gitlab-ci.yml.
W API GitLaba na razie nie ma możliwości zmiany czasu cięcia CI/CD, a on jest tam mały. Należy go zwiększyć, powiedzmy, do 1d.
Na szczęście GitLab potrafi uruchamiać nie tylko na podstawie commitów, ale i zgodnie z harmonogramem, to dokładnie to, czego potrzebujemy.
Teraz o skrypcie opakowującym.
Postawiliśmy następujące wymagania dla tego skryptu:
- Musi się uruchamiać zarówno jako runner, jak i ręcznie z konsoli z takim samym funkcjonalnością.
- Musi mieć obsługę błędów:
- kod powrotu.
- wyszukiwanie ciągu w logu. Przykład: dla nas błędem może być komunikat, który program nie uznaje za krytyczny.
- Czas oczekiwania przetwarzania. Czas wykonania powinien być rozsądny.
- Potrzebujemy szczegółowego logu. Ale tylko w przypadku błędu.
- Przeprowadza się również szereg testów przed rozpoczęciem.
- Kilka drobnych udogodnień, które uznaliśmy za przydatne w procesie wsparcia:
- Uruchomienie i zakończenie jest rejestrowane w dzienniku lokalnej maszyny. Pomaga to powiązać błędy systemowe z działaniem kopii zapasowej.
- Część logu błędów, gdy występują, jest wydawana w stdout, cały log zapisywany jest w osobnym pliku. Wygodnie jest od razu spojrzeć w CI i ocenić błąd, jeśli jest trywialny.
- Tryby debugowania.
Pełny log jest przechowywany jako artefakt w GitLab, jeśli nie ma błędów, log jest usuwany. Skrypt piszemy w bashu.
Będziemy wdzięczni za wszelkie propozycje i uwagi dotyczące open source — zapraszamy.
Jak to działa
Na node, który jest kopii zapasowej, uruchamiany jest runner z wykonawcą w bashu. W schedulerze w specjalnym repozytorium uruchamiane jest job CI/CD. Runner uruchamia skrypt jako uniwersalną nakładkę dla takich zadań, w nim przechodzą kontrole ważności repozytorium kopii zapasowej, punktów montowania i wszystkiego, co zechcemy, następnie wykonywane jest tworzenie kopii zapasowej i oczyszczanie starego. Gotowa kopia zapasowa jest wysyłana na S3.
Działamy w ten sposób — to zewnętrzny dostawca AWS lub rosyjski odpowiednik (jest to szybsze i dane nie opuszczają RF). Albo instalujemy klientowi oddzielny klaster minio na jego terenie do tych celów. Zwykle tak robimy z powodów bezpieczeństwa, gdy klient całkowicie nie chce, aby dane opuściły ich kontur.
Nie skorzystaliśmy z funkcji wysyłania kopii zapasowej przez ssh. To nie zwiększa bezpieczeństwa, a możliwości sieciowe dostawcy S3 są znacznie wyższe niż jednego naszego serwera ssh.
Aby zabezpieczyć się przed hakerem na lokalnej maszynie — ponieważ może on usunąć dane na S3, konieczne jest włączenie wersjonowania.
Kopia zapasowa jest zawsze szyfrowana.
Borg ma tryb bez szyfrowania. none, ale zdecydowanie nie zalecamy jego włączania. W tym trybie nie będzie nie tylko szyfrowania, ale nie oblicza się sumy kontrolnej tego, co jest zapisywane, a więc integralność można sprawdzić tylko pośrednio, według indeksów.
Oddzielny scheduler przeprowadza kontrolę kopii zapasowych pod kątem integralności indeksów i zawartości. Kontrola odbywa się powoli i długo, dlatego uruchamiamy ją osobno raz w miesiącu. Może trwać kilka dni.
Readme w języku rosyjskim
Główne funkcje
prepareprzygotowanietestchecksprawdzanie gotowościmaincommandgłówna komendaforcepostscriptfunkcja, która jest wykonywana na końcu lub w przypadku błędu. Używamy jej, aby odmontować partycję.
Funkcje serwisowe
cleanuprejestrujemy błędy lub usuwamy plik dziennika.checklogparsujemy dziennik w poszukiwaniu błędów.retmenedżer wyjścia.checktimeoutsprawdzanie czasu oczekiwania.
Środowisko
VERBOSE=1natychmiastowe wyświetlanie błędów na ekranie (stdout).SAVELOGSONSUCCES=1zapisujemy dziennik przy sukcesie.INIT_REPO_IF_NOT_EXIST=1Tworzymy repozytorium, jeśli nie istnieje. Domyślnie wyłączone.TIMEOUTmaksymalny czas na główną operację. Możesz ustawić 'm', 'h' lub 'd' na końcu.
Tryb przechowywania starych kopii. Domyślnie:
KEEP_DAILY=7KEEP_WEEKLY=4KEEP_MONTHLY=6
Zmienne wewnątrz skryptu
ERROR_STRING— ciąg do sprawdzenia w dzienniku pod kątem błędu.EXTRACT_ERROR_STRING— wyrażenie pokazujące ciąg w przypadku błędu.KILL_TIMEOUT_SIGNAL— sygnał do zabicia procesu, jeśli wystąpił timeout.TAIL— ile linii z błędami wyświetlić na ekranie.COLORMSG— kolor wiadomości (domyślnie żółty).
Skrypt, nazywany roboczo wordpress, ma na celu również tworzenie kopii zapasowych bazy mysql. Oznacza to, że można go używać do jednorazowych instalacji Nexcloud, gdzie można także wykonać kopię zapasową bazy. Wygoda polega nie tylko na tym, że wszystko jest w jednym miejscu, ale także na tym, że zawartość bazy jest zbliżona do zawartości plików, ponieważ różnica czasowa jest minimalna.
Restic vs Borg
Porównania Borg i Restic są dostępne również , a naszym celem nie było stworzenie jeszcze jednego, ale swojego. Ważne było dla nas, jak to będzie wyglądać na naszych danych, z naszą specyfiką. Przedstawiamy je.
Nasze kryteria wyboru, oprócz już wspomnianych (deduplikacja, szybkie przywracanie itp.):
- Odporność na niedokończoną pracę. Sprawdzenie na kill -9.
- Rozmiar na dysku.
- Wymagania dotyczące zasobów (CPU, pamięć).
- Rozmiar przechowywanych blobów.
- Praca z S3.
- Sprawdzanie integralności.
Do testów wzięliśmy jednego klienta z rzeczywistymi danymi o łącznej wielkości 1,6 TB.
Warunki.
Borg nie obsługuje bezpośrednio pracy z S3, montowaliśmy jako dysk fuse, przez . Restic wysyłał dane do S3 samodzielnie.
Goofys działa bardzo szybko i dobrze, i ma , co dodatkowo przyspiesza pracę. Jest w fazie beta i, przyznać trzeba, że w testach (innych) zdarzały się awarie z utratą danych. Wygoda polega na tym, że sama procedura tworzenia kopii zapasowej nie wymaga dużego czytania, a głównie polega na zapisie, dlatego pamięć podręczna używamy tylko podczas sprawdzania integralności.
Aby zminimalizować wpływ sieci, korzystaliśmy z lokalnego dostawcy — Yandex Cloud.
Wyniki testowania porównawczego.
- Kill -9 z dalszym uruchomieniem obie przeszły pomyślnie.
- Rozmiar na dysku. Borg potrafi kompresować, dlatego wyniki są przewidywalne.
Backuper
Wymiary
Borg
562Gb
Restic
628Gb
- Po CPU
Samo w sobie borg zużywa mało przy domyślnej kompresji, ale należy oceniać razem z procesem goofys. W sumie są porównywalne i wykorzystują około 1,2 rdzenia na tej samej testowej maszynie wirtualnej. - Pamięć. Restic około 0,5Gb, Borg około 200Mb. Ale to wszystko jest nieistotne w porównaniu z pamięcią podręczną systemu. Tak więc warto przydzielić więcej pamięci.
- Różnica w rozmiarze blobów okazała się znacząca.
Backuper
Wymiary
Borg
około 500Mb
Restic
około 5Mb
- Praca z S3 z Restic jest doskonała. Praca Borg przez goofys nie budzi wątpliwości, ale zauważono, że po zakończeniu backupu warto zrobić umount, aby całkowicie zresetować pamięć podręczną. Specyfika pracy z S3 polega na tym, że niedokończone cząstki nigdy nie zostaną wysłane do koszyka, a więc niedokończone dane prowadzą do poważnych uszkodzeń.
- Sprawdzanie integralności działa dobrze w obu przypadkach, ale prędkość się znacznie różni.
Restic – 3,5 godziny.
Borg, z pamięcią podręczną plików 100Gb SSD – 5 godzin.Mniej więcej taki sam wynik prędkości, jeśli dane znajdują się na lokalnym dysku.
Borg odczytuje bezpośrednio z S3 bez pamięci podręcznej 33 godziny.Ogromnie długo.
W ostatecznym rozrachunku Borg potrafi kompresować i ma większe bloby — co sprawia, że przechowywanie i operacje GET/PUT w S3 są tańsze. Ale za to trzeba płacić bardziej skomplikowanym i wolniejszym sprawdzaniem. Jeśli chodzi o prędkość przywracania — nie zauważyliśmy różnicy. Kolejne kopie zapasowe (po pierwszym) restic wykonuje nieco dłużej, ale nie znacząco.
Nie na ostatnim miejscu w wyborze stał rozmiar społeczności.
I wybraliśmy borg.
Kilka słów o kompresji
Borg ma w arsenale doskonały nowy algorytm kompresji — zstd. Pod względem jakości kompresji nie gorszy niż gzip, ale znacznie szybszy. I porównywalny pod względem prędkości z domyślnym lz4.
Na przykład zrzut bazy MySQL kompresuje się dwa razy lepiej niż lz4 przy tej samej prędkości. Jednak doświadczenie na rzeczywistych danych pokazuje bardzo niewielką różnicę w stopniu kompresji węzłów Nextcloud.
W Borg jest dosyć bonusowy tryb kompresji — jeśli plik ma dużą entropię, kompresja w ogóle nie jest stosowana, co zwiększa prędkość działania. Jest włączana opcją przy tworzeniu
-C auto,zstd
dla algorytmu zstd
A więc z tą opcją w porównaniu z domyślną kompresją uzyskaliśmy
560 Gb i 562 Gb odpowiednio. Jak przypominam, dane z powyższego przykładu bez kompresji dają wynik 628 Gb. Wynik z różnicą 2 Gb zaskoczył nas nieco, ale uznaliśmy, że i tak wybierzemy. auto,zstd.
Metoda weryfikacji kopii zapasowej
Na podstawie harmonogramu uruchamiana jest wirtualna maszyna bezpośrednio u dostawcy lub u klienta, co znacznie zmniejsza obciążenie sieci. Przynajmniej jest to tańsze niż uruchamianie u siebie i przesyłanie ruchu.
goofys --cache "--free:5%:/mnt/cache" -o allow_other --endpoint https://storage.yandexcloud.net --file-mode=0666 --dir-mode=0777 xxxxxxx.com /mnt/goofys
export BORG_PASSCOMMAND="cat /home/borg/.borg-passphrase"
borg list /mnt/goofys/borg1/
borg check --debug -p --verify-data /mnt/goofys/borg1/Na tej samej zasadzie sprawdzamy pliki antywirusowe (post factum). Użytkownicy przesyłają różne dane do Nextcloud i nie wszyscy mają oprogramowanie antywirusowe. Sprawdzenie w momencie przesyłania zajmuje zbyt dużo czasu i przeszkadza w działalności.
Skalowalność osiąga się poprzez uruchamianie runnerów na różnych węzłach z różnymi tagami.
W naszym monitoringu gromadzone są statusy kopii zapasowych przez API GitLab w jednym oknie, w razie potrzeby łatwo zauważyć problemy, które również łatwo można zlokalizować.
Podsumowanie
Ostatecznie dokładnie wiemy, że robimy kopie zapasowe, że nasze kopie zapasowe są ważne, problemy, które się z nimi pojawiają, zajmują mało czasu i są rozwiązywane na poziomie dyżurnego administratora. Kopie zapasowe zajmują naprawdę mało miejsca w porównaniu z tar.gz lub Bacula.
Źródło: habr.com
