Jak z fio sprawdzić dyski na wystarczającą wydajność dla etcd

Przyp. tłum.: ten artykuł podsumowuje wyniki mini-badania przeprowadzonego przez inżynierów IBM Cloud w poszukiwaniu rozwiązania rzeczywistego problemu związanego z eksploatacją bazy danych etcd. Dla nas była to istotna kwestia, jednak sposób rozumowania i działań autorów może być interesujący także w szerszym kontekście.

Jak z fio sprawdzić dyski na wystarczającą wydajność dla etcd

Krótki przegląd całego artykułu: fio i etcd

Wydajność klastra etcd silnie zależy od prędkości magazynu, na którym opiera się jego działanie. Aby monitorować wydajność, etcd eksportuje różne metryki Prometheus. Jedną z nich jest wal_fsync_duration_seconds. W dokumentacji etcd pisze się, można uznać magazyn za wystarczająco szybki, jeśli 99. percentyl tej metryki nie przekracza 10 ms…

Jeśli zastanawiasz się nad zorganizowaniem klastra etcd na maszynach z systemem Linux i chcesz sprawdzić, czy twoje dyski (np. SSD) są wystarczająco szybkie, polecamy skorzystanie z popularnego testera I/O o nazwie fio. Wystarczy uruchomić następujące polecenie (katalog test-data powinien znajdować się w zamontowanej partycji testowanego dysku):

fio --rw=write --ioengine=sync --fdatasync=1 --directory=test-data --size=22m --bs=2300 --name=mytest

Teraz wystarczy spojrzeć na wyniki i sprawdzić, czy 99. percentyl fdatasync miesci się w 10 ms. Jeśli tak, to znaczy, że Twój dysk działa wystarczająco szybko. Oto przykład wyników:

fsync/fdatasync/sync_file_range:
  sync (usec): min=534, max=15766, avg=1273.08, stdev=1084.70
  sync percentiles (usec):
   | 1.00th=[ 553], 5.00th=[ 578], 10.00th=[ 594], 20.00th=[ 627],
   | 30.00th=[ 709], 40.00th=[ 750], 50.00th=[ 783], 60.00th=[ 1549],
   | 70.00th=[ 1729], 80.00th=[ 1991], 90.00th=[ 2180], 95.00th=[ 2278],
   | 99.00th=[ 2376], 99.50th=[ 9634], 99.90th=[15795], 99.95th=[15795],
   | 99.99th=[15795]

Kilka uwag:

  1. W powyższym przykładzie dostosowaliśmy parametry --size i --bs do konkretnego przypadku. Aby uzyskać sensowny wynik z fio, podawaj wartości odpowiednie do twojego scenariusza użycia. O tym, jak je dobrać, będzie mowa poniżej.
  2. Podczas testu jedynie fio obciąża dyskową podsystem. W rzeczywistym życiu z pewnością na dysk będą pisały również inne procesy (oprócz tych związanych z wal_fsync_duration_seconds). Taki dodatkowy ładunek może prowadzić do wzrostu wal_fsync_duration_seconds. Innymi słowy, jeśli 99. percentyl uzyskany w wyniku testu z fio, znajduje się tylko nieznacznie poniżej 10 ms, istnieje duże prawdopodobieństwo, że wydajność magazynu jest niewystarczająca.
  3. Aby przeprowadzić test, potrzebujesz wersji fio nie niższą niż 3.5, ponieważ starsze wersje nie agregują wyników fdatasync w postaci percentyli.
  4. Powyższy wynik to tylko mały fragment całkowitego wyniku fio.

Szczegóły dotyczące fio i etcd

Kilka słów o WAL-ach etcd

Z reguły bazy danych korzystają z logowania wstecznego (write-ahead logging, WAL). Dotyczy to również etcd. Dyskusja na temat WAL wykracza poza zakres tego artykułu, jednak dla naszych potrzeb warto wiedzieć, że każdy członek klastra etcd przechowuje WAL w trwałym magazynie. etcd zapisuje niektóre operacje z magazynem klucz-wartość (np. aktualizacje) w WAL przed ich wykonaniem. Jeśli węzeł ulegnie awarii i zostanie ponownie uruchomiony pomiędzy snapshotami, etcd będzie mógł przywrócić transakcje, które miały miejsce od ostatniego snapshotu, kierując się zawartością WAL.

W związku z tym, za każdym razem, gdy klient dodaje klucz do magazynu KV lub aktualizuje wartość istniejącego klucza, etcd dodaje opis operacji do WAL, który jest zwykłym plikiem w trwałym magazynie. Zanim etcd będzie mogło kontynuować, MUSI być w 100% pewne, że zapis do WAL został rzeczywiście zapisany. Aby to osiągnąć w systemie Linux, nie wystarczy użyć wywołania systemowego write, ponieważ sama operacja zapisu na nośniku fizycznym może być opóźniona. Na przykład, Linux przez jakiś czas może utrzymywać zapis WAL w pamięci podręcznej jądra (np. w pamięci podręcznej stron). Aby zapewnić, że dane zostały zapisane na nośniku, po zapisie należy użyć wywołania systemowego fdatasync — dokładnie tak postępuje etcd (jak widać w przykładzie poniższego wyniku strace; tutaj 8 — deskryptor pliku WAL):

21:23:09.894875 lseek(8, 0, SEEK_CUR)   = 12808 
21:23:09.894911 write(8, ".      20210220361223255266632$10 20103026"34"rn3fo"..., 2296) = 2296 
21:23:09.895041 fdatasync(8)            = 0

Niestety, zapis do trwałego magazynu zajmuje trochę czasu. Wydłużone wykonanie wywołania fdatasync może wpływać na wydajność etcd. W dokumentacji przechowywania jest określany, podano, że dla wystarczającej wydajności 99-ty percentyl czasu trwania wszystkich wywołań fdatasync przy zapisie do pliku WAL powinien wynosić mniej niż 10 ms. Istnieją również inne metryki związane z przechowywaniem, ale ten artykuł skupi się właśnie na tej.

Ocena magazynu przy użyciu fio

Można ocenić, czy dane magazyn nadaje się do użycia z etcd, za pomocą narzędzia fio — popularny tester I/O. Należy pamiętać, że dyskowy input-output może następować na różne sposoby: sync/async, wiele różnych klas wywołań systemowych itp. Ciemną stroną jest to, że fio jest niezwykle skomplikowane w użyciu. Narzędzie ma wiele parametrów, a różne kombinacje ich wartości prowadzą do zupełnie różnych wyników. Aby uzyskać sensowną ocenę w przypadku etcd, musisz upewnić się, że obciążenie zapisu generowane przez fio możliwie najbardziej przypomina obciążenie etcd podczas zapisu do plików WAL:

  • To oznacza, że generowane fio obciążenie przynajmniej powinno stanowić serię sekwencyjnych zapisów do pliku, gdzie każda operacja zapisu składa się z wywołania systemowego write, po którym następuje fdatasync.
  • Aby włączyć sekwencyjny zapis, należy określić flagę --rw=write.
  • Aby fio zapisywał przy użyciu wywołań write (a nie innych wywołań systemowych — na przykład, pwrite), użyj flagi --ioengine=sync.
  • Na koniec, flaga --fdatasync=1 gwarantuje, że za każdym write należy fdatasync.
  • Dwa inne parametry w naszym przykładzie: --size i --bs — mogą się zmieniać w zależności od konkretnego scenariusza użycia. W następnej sekcji zostanie opisane ich ustawienie.

Dlaczego wybraliśmy fio i jak się nauczyliśmy go konfigurować

Notatka ta powstała z realnego przypadku, z którym się spotkaliśmy. Mieliśmy klaster na Kubernetes v1.13 z monitoringiem w Prometheus. Jako magazyn dla etcd v3.2.24 służyły dyski SSD. Metryki etcd pokazywały zbyt wysokie opóźnienia fdatasync, nawet gdy klaster był bezczynny. Te metryki wydawały nam się dość wątpliwe, a my nie byliśmy pewni, co one właściwie przedstawiają. Dodatkowo, klaster składał się z maszyn wirtualnych, więc nie mogliśmy stwierdzić, czy opóźnienia były związane z wirtualizacją, czy SSD były całkowicie odpowiedzialne.

Ponadto rozważaliśmy różne zmiany w konfiguracji sprzętu i oprogramowania, więc potrzebny był sposób ich oceny. Oczywiście można by uruchomić etcd w każdej konfiguracji i sprawdzić odpowiednie metryki Prometheus, ale wymagałoby to znacznych wysiłków. Potrzebowaliśmy prostego sposobu, aby ocenić konkretną konfigurację. Chcieliśmy zweryfikować nasze zrozumienie metryk Prometheus płynących z etcd.

Do tego należało rozwiązać dwa problemy:

  • Po pierwsze, jak wygląda obciążenie I/O generowane przez etcd podczas zapisywania do plików WAL? Jakie wywołania systemowe są używane? Jaki jest rozmiar bloków zapisu?
  • Po drugie, załóżmy, że mamy odpowiedzi na powyższe pytania. Jak odtworzyć odpowiednie obciążenie z fio? Ведь fio — niezwykle elastyczne narzędzie z dużą ilością parametrów (co można łatwo zweryfikować, na przykład, tutaj ­— przyp. tłum.).

Rozwiązaliśmy oba problemy, stosując tę samą metodę opartą na komendach lsof i strace:

  • Dzięki lsof można przejrzeć wszystkie deskryptory plików używane przez proces, jak i pliki, do których się odnoszą.
  • Dzięki strace można analizować już uruchomiony proces lub uruchomić proces i go obserwować. Komenda wyświetla wszystkie wywołania systemowe dokonane przez dany proces oraz, w razie potrzeby, jego potomków. To ostatnie jest istotne dla procesów, które forkowały się, a etcd jest jednym z takich procesów.

Pierwszą rzeczą, którą zrobiliśmy, było użycie strace do zbadania serwera etcd w klastrze Kubernetes, podczas gdy był bezczynny.

W ten sposób odkryto, że bloki zapisu w WAL są bardzo ściśle skonsolidowane, a rozmiar większości wynosił w przedziale 2200-2400 bajtów. To dlatego w komendzie na początku tego artykułu użyto flagi --bs=2300 (bs — rozmiar w bajtach każdego bloku zapisu w fio).

Zauważ, że rozmiar bloków zapisu etcd może się różnić w zależności od wersji, wdrożenia, wartości parametrów itp. — ma to wpływ na czas trwania fdatasync. Jeśli masz podobny scenariusz użycia, przeanalizuj za pomocą strace swoje procesy etcd, aby uzyskać aktualne wartości.

Następnie, aby uzyskać jasny i całościowy obraz działania etcd z systemem plików, uruchomiliśmy go z strace flagami -ffttT. To pozwoliło objąć procesy potomne i zapisać wyjście każdego w osobnym pliku. Ponadto uzyskano szczegółowe informacje o czasie rozpoczęcia i trwaniu każdego wywołania systemowego.

Skorzystaliśmy również z komendy lsof, aby potwierdzić nasze zrozumienie wyjścia strace pod względem tego, który deskryptor pliku był używany do jakiego celu. Otrzymaliśmy wyjście strace, podobne do tego, które zostało podane powyżej. Statystyczne manipulacje z czasami synchronizacji potwierdziły, że metryka wal_fsync_duration_seconds od etcd odpowiada wywołaniom fdatasync z deskryptorami plików WAL.

Aby wygenerować za pomocą fio Obciążenie robocze podobne do obciążenia z etcd, została zbadana dokumentacja narzędzia i dobrano parametry odpowiednie dla naszego zadania. Upewniliśmy się, że są zaangażowane odpowiednie wywołania systemowe i potwierdziliśmy ich czas trwania, uruchamiając fio z strace (jak to miało miejsce w przypadku etcd).

Szczególną uwagę zwrócono na określenie wartości parametru --size. Reprezentuje on całkowite obciążenie I/O generowane przez narzędzie fio. W naszym przypadku jest to całkowita liczba bajtów zapisanego na nośniku. Jest ona wprost proporcjonalna do liczby wywołań write (i fdatasync). Dla określonego bs liczby wywołań fdatasync równa się size / bs.

Ponieważ interesował nas percentyl, staraliśmy się, aby liczba prób była wystarczająco duża dla statystycznej istotności. Postanowiliśmy, że 10^4 (co odpowiada rozmiarowi 22 MB) będzie wystarczające. Mniejsze wartości parametru --size generowały bardziej wyraźny szum (na przykład wywołania fdatasync, które zajmują znacznie więcej czasu niż zwykle i wpływają na 99. percentyl).

Teraz wszystko w twoich rękach

W artykule pokazano, jak za pomocą fio można ocenić, czy nośnik przeznaczony do użycia z etcd jest wystarczająco szybki. Teraz wszystko w twoich rękach! Możesz badać maszyny wirtualne z pamięcią opartą na SSD w serwisie IBM Cloud.

P.S. od tłumacza

Z gotowymi przykładami zastosowania fio do rozwiązywania innych zadań można zapoznać się w dokumentacji lub bezpośrednio w repozytorium projektu. (jest ich tam znacznie więcej, niż wspomniano w dokumentacji).

P.P.S. od tłumacza

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster