
Cześć, niedawno natknąłem się na interesujące zadanie skonfigurowania magazynu do tworzenia kopii zapasowych dużej liczby urządzeń blokowych.
Co tydzień wykonujemy kopie zapasowe wszystkich maszyn wirtualnych w naszej chmurze, dlatego musimy umieć obsługiwać tysiące kopii zapasowych i robić to maksymalnie szybko i efektywnie.
Niestety standardowe konfiguracje RAID5, RAID6 w tym przypadku nie będą odpowiednie, ponieważ proces przywracania na tak dużych dyskach jak nasze będzie niezmiernie długi i najprawdopodobniej nigdy się nie skończy.
Rozważmy jakie są alternatywy:
— odpowiednik RAID5, RAID6, ale z konfigurowalnym poziomem parzystości. W tym przypadku replikacja odbywa się nie blokowo, a dla każdego obiektu z osobna. Najprostszym sposobem na wypróbowanie erasure coding jest wdrożenie .
— to obecnie jeszcze niewydana funkcjonalność ZFS. W przeciwieństwie do RAIDZ DRAID ma rozproszony blok parzystości i przy przywracaniu angażuje od razu wszystkie dyski w macierzy, dzięki czemu lepiej znosi awarie dysków i szybciej się odbudowuje po awarii.


Dysponujemy serwerem Fujitsu Primergy RX300 S7 z procesorem Intel Xeon CPU E5-2650L 0 @ 1.80GHz, dziewięcioma modułami pamięci RAM Samsung DDR3-1333 8Gb PC3L-10600R ECC Registered (M393B1K70DH0-YH9), macierzą dyskową Supermicro SuperChassis 847E26-RJBOD1, podłączoną przez Dual LSI SAS2X36 Expander i 45 dysków Seagage ST6000NM0115-1YZ110 w 6TB każdy.
Zanim podejmiemy decyzję, musimy najpierw wszystko odpowiednio przetestować.
W tym celu przygotowałem się i przeprowadziłem testy różnych konfiguracji. Użyłem minio, które działało jako backend S3 i uruchomiłem je w różnych trybach z różną liczbą celów.
Głównie testowano przypadek minio w erasure coding vs software raid z taką samą liczbą dysków i dysków parzystości, a więc: RAID6, RAIDZ2 i DRAID2.
Dla przypomnienia: gdy uruchamiasz minio z jednym celem, to minio działa w trybie bramki S3, udostępniając Twój lokalny system plików jako magazyn S3. Natomiast gdy uruchomisz minio z wieloma celami, automatycznie włączy się tryb Erasure Coding, który rozprzestrzenia dane pomiędzy Twoimi celami, zapewniając odporność na awarie.
Domyślnie minio dzieli cele na grupy po 16 dysków, gdzie na każdą grupę przypada po 2 pary. Oznacza to, że jednocześnie mogą awarii ulec dwa dyski bez utraty danych.
Do testowania wydajności użyłem 16 dysków po 6 TB każdy i pisałem na nich małe obiekty o rozmiarze 1 MB, co najdokładniej odzwierciedlało nasze przyszłe obciążenie, ponieważ wszystkie nowoczesne narzędzia do tworzenia kopii zapasowych dzielą dane na bloki o kilku megabajtach i zapisują je w ten sposób.
Do przeprowadzenia benchmarku użyto narzędzia s3bench uruchamianego na zdalnym serwerze, które wysyłało do minio dziesiątki tysięcy takich obiektów równocześnie w setkach wątków. Następnie w ten sam sposób próbowało je zażądać z powrotem.
Wyniki benchmarku przedstawione są w tabeli poniżej:

Jak widzimy, minio w trybie własnego erasure coding działa znacznie gorzej podczas zapisu niż minio uruchomiony na programowym RAID6, RAIDZ2 i DRAID2 w tej samej konfiguracji.
Osobno poproszono mnie minio na ext4 vs XFS. Co ciekawe, dla mojego typu obciążenia XFS okazał się znacznie wolniejszy niż ext4.
W pierwszej części testów Mdadm wykazał przewagę nad ZFS, ale później , że można poprawić wydajność ZFS, ustawiając następujące opcje:
xattr=sa atime=off recordsize=1Mi po tym testy z ZFS stały się znacznie lepsze.
Można również zauważyć, że DRAID nie daje szczególnej przewagi w wydajności nad RAIDZ, ale teoretycznie powinien być znacznie bezpieczniejszy.
W dwóch ostatnich testach próbowałem również przenieść metadane (special) i ZIL (log) na lustrzane z SSD. Jednak przeniesienie metadanych nie przyniosło dużych korzyści w szybkości zapisu, a przy przenoszeniu ZIL moje osiągnęły sufit z 100% utylizacją, więc uważam ten test za nieudany. Nie wykluczam, że gdybym miał szybsze dyski SSD, to mogłoby to znacząco poprawić moje wyniki, ale niestety ich nie miałem.
Ostatecznie zdecydowałem się na użycie DRAID i mimo swojego statusu beta, jest to najszybsze i najefektywniejsze rozwiązanie do przechowywania w naszym przypadku.
Stworzyłem prosty DRAID2 w konfiguracji z trzema grupami i dwoma częściami rozproszonymi:
# zpool status data
pool: data
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
data ONLINE 0 0 0
draid2:3g:2s-0 ONLINE 0 0 0
sdy ONLINE 0 0 0
sdam ONLINE 0 0 0
sdf ONLINE 0 0 0
sdau ONLINE 0 0 0
sdab ONLINE 0 0 0
sdo ONLINE 0 0 0
sdw ONLINE 0 0 0
sdak ONLINE 0 0 0
sdd ONLINE 0 0 0
sdas ONLINE 0 0 0
sdm ONLINE 0 0 0
sdu ONLINE 0 0 0
sdai ONLINE 0 0 0
sdaq ONLINE 0 0 0
sdk ONLINE 0 0 0
sds ONLINE 0 0 0
sdag ONLINE 0 0 0
sdi ONLINE 0 0 0
sdq ONLINE 0 0 0
sdae ONLINE 0 0 0
sdz ONLINE 0 0 0
sdan ONLINE 0 0 0
sdg ONLINE 0 0 0
sdac ONLINE 0 0 0
sdx ONLINE 0 0 0
sdal ONLINE 0 0 0
sde ONLINE 0 0 0
sdat ONLINE 0 0 0
sdaa ONLINE 0 0 0
sdn ONLINE 0 0 0
sdv ONLINE 0 0 0
sdaj ONLINE 0 0 0
sdc ONLINE 0 0 0
sdar ONLINE 0 0 0
sdl ONLINE 0 0 0
sdt ONLINE 0 0 0
sdah ONLINE 0 0 0
sdap ONLINE 0 0 0
sdj ONLINE 0 0 0
sdr ONLINE 0 0 0
sdaf ONLINE 0 0 0
sdao ONLINE 0 0 0
sdh ONLINE 0 0 0
sdp ONLINE 0 0 0
sdad ONLINE 0 0 0
spares
s0-draid2:3g:2s-0 AVAIL
s1-draid2:3g:2s-0 AVAIL
errors: No known data errorsDobrze, poradziliśmy sobie z przechowywaniem, teraz o tym, czym będziemy robić kopie zapasowe. Tutaj natychmiast chciałbym opowiedzieć o trzech rozwiązaniach, które mogłem przetestować, a są to:
— fork , specjalistyczne rozwiązanie do tworzenia kopii zapasowych urządzeń blokowych, ma bliską integrację z Ceph. Potrafi pobierać różnice między migawkami i tworzyć na ich podstawie kopie zapasowe inkrementalne. Obsługuje wiele backendów przechowywania, w tym zarówno lokalne, jak i S3. Wymaga osobnej bazy danych do przechowywania tablicy haseł deduplikacji. Wśród wad: napisany w Pythonie, ma nieco nieodpowiedzialny interfejs CLI.
— fork , od dawna znane i sprawdzone narzędzie do tworzenia kopii zapasowych, potrafi tworzyć kopie danych i dobrze je deduplikować. Obsługuje zapisywanie kopii lokalnie i na zdalnym serwerze za pomocą scp. Może tworzyć kopie zapasowe urządzeń blokowych przy uruchomieniu z flagą --special, wśród wad: podczas tworzenia kopii zapasowej repozytorium jest całkowicie zablokowane, dlatego dla każdej wirtualnej maszyny zaleca się tworzenie osobnego repozytorium, w zasadzie nie jest to problem, ponieważ ich utworzenie jest bardzo łatwe.
— aktywnie rozwijający się projekt, napisany w Go, wystarczająco szybki i obsługujący wiele backendów przechowywania, w tym zarówno lokalne przechowywanie, jak i scp, S3 i wiele innych. Osobno warto zauważyć, że istnieje specjalnie stworzony dla restic, który umożliwia najszybszy eksport przechowywania do wykorzystania zdalnego. Spośród wszystkich wymienionych, najbardziej mi się spodobał. Umie tworzyć kopie zapasowe z stdin. Prawie nie ma zauważalnych wad, ale ma kilka szczególnych cech:
Po pierwsze, próbowałem użyć go w trybie wspólnego repozytorium dla wszystkich wirtualnych maszyn (jak Benji) i działało to całkiem nieźle, ale operacje przywracania zajmowały dość dużo czasu, ponieważ za każdym razem przed przywróceniem restic próbuje odczytać metadane wszystkich kopii zapasowych. Ten problem łatwo rozwiązano, jak w przypadku borg, tworząc osobne repozytorium dla każdej wirtualnej maszyny. To podejście okazało się również bardzo efektywne dla zarządzania kopiami zapasowymi. Osobne repozytoria mogą mieć osobne hasło do dostępu do danych, a także nie musimy obawiać się, że globalne repozytorium ulegnie jakiejkolwiek awarii. Tworzenie nowych repozytoriów można również zrealizować tak łatwo, jak w borg backup.
W każdym przypadku deduplikacja jest przeprowadzana tylko w stosunku do poprzedniej wersji kopii zapasowej, gdzie poprzednia kopia zapasowa określana jest na podstawie ścieżki określonej dla danej kopii zapasowej, więc jeśli robisz kopie zapasowe różnych obiektów z stdin do wspólnego repozytorium, nie zapomnij wskazać opcji
--stdin-filename, lub jawnie za każdym razem wskazywać opcję--parent.
Po drugie, przywracanie do stdout zajmuje znacznie więcej czasu niż przywracanie na system plików ze względu na swoją równoległość. W przyszłości planowane jest dodanie bliższego wsparcia dla kopii zapasowych dla urządzeń blokowych.
Po trzecie, obecnie zaleca się korzystanie z , ponieważ wersja 0.9.6 ma błąd związany z długim przywracaniem dużych plików.
Aby przetestować wydajność kopii zapasowej oraz szybkość zapisu / przywracania z kopii zapasowej, stworzyłem osobne repozytorium i spróbowałem wykonać kopię małego obrazu maszyny wirtualnej (21 GB). Wykonano dwie kopie zapasowe bez zmian w oryginale, korzystając z każdej z wymienionych metod, aby sprawdzić, jak szybko / wolno kopiowane są deduplikowane dane.

Jak możemy zauważyć, Borg Backup ma najlepszy współczynnik efektywności początkowej kopii zapasowej, ale przegrywa pod względem szybkości zarówno zapisu, jak i przywracania.
Restic okazał się szybszy od Benji Backup, ale dłużej przywraca do stdout, a pisanie bezpośrednio do urządzenia blokowego, niestety, na razie mu nie wychodzi.
Ważąc wszystkie za i przeciw, postanowiłem zatrzymać się na restic z rest-server , jako na najbardziej wygodnym i obiecującym rozwiązaniu do kopii zapasowej.
W tym screencastie możesz zobaczyć, jak 10-gigabitowy kanał jest całkowicie wykorzystywany przy kilku jednocześnie uruchomionych operacjach kopii zapasowej. Warto zauważyć, że obciążenie dysków nie przekracza 30%.
Z uzyskanym rozwiązaniem jestem bardziej niż zadowolony!
Źródło: habr.com
