Szybkość przechowywania odpowiednia dla etcd? Zapytajmy fio

Szybkość przechowywania odpowiednia dla etcd? Zapytajmy fio

Krótka historia o fio i etcd

Wydajność klastra itd w dużej mierze zależy od wydajności jego przechowywania. etcd eksportuje niektóre metryki do Prometheusw celu dostarczenia żądanych informacji o wydajności pamięci masowej. Na przykład metryka wal_fsync_duration_seconds. Dokumentacja dla etcd mówi: Aby pamięć została uznana za wystarczająco szybką, 99. percentyl tej metryki musi być krótszy niż 10 ms. Jeśli planujesz uruchomić klaster etcd na maszynach z systemem Linux i chcesz ocenić, czy twoja pamięć masowa jest wystarczająco szybka (np. SSD), możesz użyć fio jest popularnym narzędziem do testowania operacji wejścia/wyjścia. Uruchom następującą komendę, gdzie dane testowe to katalog w punkcie podłączenia magazynu:

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

Wystarczy spojrzeć na wyniki i sprawdzić, czy 99. percentyl czasu trwania fdatasync mniej niż 10 ms. Jeśli tak, masz dość szybką pamięć masową. Oto przykład wyników:

  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]

Uwagi

  • Dostosowaliśmy opcje --size i --bs dla naszego konkretnego scenariusza. Aby uzyskać użyteczny wynik z fio, podaj własne wartości. Gdzie je zdobyć? Czytać jak nauczyliśmy się konfigurować fio.
  • Podczas testowania całe obciążenie we/wy pochodzi z fio. W rzeczywistym scenariuszu prawdopodobnie do magazynu będą napływać inne żądania zapisu oprócz tych związanych z wal_fsync_duration_seconds. Dodatkowe obciążenie zwiększy wartość wal_fsync_duration_seconds. Jeśli więc 99. percentyl zbliża się do 10 ms, oznacza to, że Twoja pamięć ma zbyt małą prędkość.
  • Weź wersję fio nie mniej niż 3.5 (poprzednie nie pokazują percentyli czasu trwania fdatasync).
  • Powyżej znajduje się tylko fragment wyników z fio.

Długa historia o fio i etcd

Co to jest WAL w etcd

Zwykle używają baz danych dziennik zapisu z wyprzedzeniem; etcd też go używa. Nie będziemy tutaj szczegółowo omawiać dziennika zapisu z wyprzedzeniem (WAL). Wystarczy, że wiemy, że każdy członek klastra etcd utrzymuje go w pamięci trwałej. etcd zapisuje każdą operację klucz-wartość (taką jak aktualizacja) do WAL przed zastosowaniem jej w sklepie. Jeśli jeden z członków magazynu ulegnie awarii i uruchomi się ponownie między migawkami, może lokalnie przywrócić transakcje od ostatniej migawki według zawartości WAL.

Gdy klient dodaje klucz do magazynu klucz-wartość lub aktualizuje wartość istniejącego klucza, etcd rejestruje operację w WAL, który jest zwykłym plikiem w pamięci trwałej. etcd MUSI być całkowicie pewien, że wpis WAL rzeczywiście wystąpił przed kontynuowaniem przetwarzania. W Linuksie jedno wywołanie systemowe to za mało. napisać, ponieważ rzeczywisty zapis do pamięci fizycznej może być opóźniony. Na przykład Linux może przez pewien czas przechowywać wpis WAL w pamięci podręcznej w pamięci jądra (takiej jak pamięć podręczna stron). A żeby dane zostały dokładnie zapisane do pamięci trwałej, po zapisie potrzebne jest wywołanie systemowe fdatasync, a etcd po prostu z niego korzysta (jak widać w wyniku pracy strace, gdzie 8 to deskryptor pliku WAL):

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

Niestety, zapisywanie w pamięci trwałej nie następuje natychmiast. Jeśli wywołanie fdatasync jest powolne, ucierpi na tym wydajność systemu etcd. Dokumentacja dla etcd mówiże pamięć jest uważana za wystarczająco szybką, jeśli w 99. percentylu wywołania fdatasync zajmują mniej niż 10 ms, aby zapisać do pliku WAL. Istnieją inne przydatne wskaźniki dotyczące przechowywania, ale w tym poście mówimy tylko o tym wskaźniku.

Szacowanie pamięci za pomocą fio

Jeśli chcesz ocenić, czy twoja pamięć masowa jest odpowiednia dla etcd, użyj fio, bardzo popularnego narzędzia do testowania obciążenia we/wy. Należy pamiętać, że operacje dyskowe mogą być bardzo różne: synchroniczne i asynchroniczne, wiele klas wywołań systemowych itp. W rezultacie fio jest dość trudne w użyciu. Ma wiele parametrów, a różne kombinacje ich wartości powodują bardzo różne obciążenia we/wy. Aby uzyskać odpowiednie wartości dla etcd, powinieneś upewnić się, że testowe obciążenie zapisu z fio jest jak najbardziej zbliżone do rzeczywistego obciążenia z etcd podczas zapisywania plików WAL.

Dlatego fio powinno co najmniej utworzyć obciążenie serii sekwencyjnych zapisów do pliku, każdy zapis będzie składał się z wywołania systemowego napisaćpo którym następuje wywołanie systemowe fdatasync. Sekwencyjne zapisy do fio wymagają opcji --rw=write. Aby fio używało wywołania systemowego write podczas pisania, zamiast pisać, należy określić parametr --ioengine=sync. Wreszcie, aby wywołać fdatasync po każdym zapisie, należy dodać parametr --fdatasync=1. Pozostałe dwie opcje w tym przykładzie (--size i -bs) są specyficzne dla skryptu. W następnej sekcji pokażemy, jak je skonfigurować.

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

W tym poście opisujemy prawdziwy przypadek. Mamy klaster Kubernetes v1.13, którą monitorowaliśmy za pomocą Prometheusa. etcd v3.2.24 był hostowany na dysku SSD. Metryki Etcd wykazały zbyt duże opóźnienia fdatasync, nawet gdy klaster nic nie robił. Metryki były dziwne i tak naprawdę nie wiedzieliśmy, co oznaczają. Klaster składał się z maszyn wirtualnych, konieczne było zrozumienie w czym tkwił problem: w fizycznych dyskach SSD czy w warstwie wirtualizacji. Ponadto często dokonywaliśmy zmian w konfiguracji sprzętu i oprogramowania i potrzebowaliśmy sposobu na ocenę ich wyników. Moglibyśmy uruchomić etcd w każdej konfiguracji i spojrzeć na metryki Prometheusa, ale to zbyt duży kłopot. Szukaliśmy dość prostego sposobu na ocenę konkretnej konfiguracji. Chcieliśmy sprawdzić, czy poprawnie rozumiemy metryki Prometheusa z etcd.

Ale w tym celu należało rozwiązać dwa problemy. Po pierwsze, jak wygląda obciążenie we/wy, które tworzy etcd podczas zapisywania do WAL? Jakie wywołania systemowe są używane? Jaki jest rozmiar rekordów? Po drugie, jeśli odpowiemy na te pytania, jak odtworzyć podobne obciążenie za pomocą fio? Nie zapominaj, że fio to bardzo elastyczne narzędzie z wieloma opcjami. Rozwiązaliśmy oba problemy za pomocą jednego podejścia - za pomocą poleceń lsof и strace. lsof wyświetla wszystkie deskryptory plików używane przez proces i powiązane z nimi pliki. Za pomocą strace możesz sprawdzić już działający proces lub uruchomić proces i zbadać go. strace wypisuje wszystkie wywołania systemowe z badanego procesu (i jego procesów potomnych). To ostatnie jest bardzo ważne, ponieważ etcd po prostu przyjmuje podobne podejście.

Po raz pierwszy użyliśmy strace do eksploracji serwera etcd dla Kubernetes, gdy klaster nie był obciążony. Zauważyliśmy, że prawie wszystkie rekordy WAL miały mniej więcej ten sam rozmiar: 2200–2400 bajtów. Dlatego w poleceniu na początku wpisu podaliśmy parametr -bs=2300 (bs oznacza rozmiar w bajtach dla każdego wpisu fio). Należy zauważyć, że rozmiar wpisu etcd zależy od wersji etcd, dystrybucji, wartości parametrów itp. i wpływa na czas trwania fdatasync. Jeśli masz podobny scenariusz, sprawdź swoje procesy etcd za pomocą strace, aby znaleźć dokładne liczby.

Następnie, aby dobrze zorientować się, co robi system plików etcd, uruchomiliśmy go za pomocą strace i opcji -ffttT. Próbowaliśmy więc zbadać procesy potomne i zapisać dane wyjściowe każdego z nich w osobnym pliku, a także uzyskać szczegółowe raporty o rozpoczęciu i czasie trwania każdego wywołania systemowego. Użyliśmy lsof, aby potwierdzić naszą analizę danych wyjściowych strace i zobaczyć, który deskryptor pliku był używany w jakim celu. Tak więc za pomocą strace uzyskano wyniki pokazane powyżej. Statystyki czasu synchronizacji potwierdziły, że wal_fsync_duration_seconds z etcd jest zgodne z wywołaniami fdatasync z deskryptorami plików WAL.

Przejrzeliśmy dokumentację fio i wybraliśmy opcje dla naszego skryptu, aby fio generowało obciążenie podobne do etcd. Sprawdziliśmy również wywołania systemowe i czas ich trwania, uruchamiając fio ze strace, podobnie jak etcd.

Starannie wybraliśmy wartość parametru --size, aby reprezentowała całe obciążenie we/wy z fio. W naszym przypadku jest to całkowita liczba bajtów zapisanych w pamięci. Okazało się, że jest wprost proporcjonalne do liczby wywołań systemowych write (i fdatasync). Dla pewnej wartości bs liczba wywołań fdatasync = size/bs. Ponieważ interesował nas percentyl, musieliśmy mieć wystarczającą liczbę próbek, aby mieć pewność, i obliczyliśmy, że 10^4 wystarczy dla nas (czyli 22 mebibajty). Jeśli opcja --size jest mniejsza, mogą wystąpić wartości odstające (na przykład kilka wywołań fdatasync trwa dłużej niż zwykle i wpływa na 99. percentyl).

Spróbuj sam

Pokazaliśmy ci, jak korzystać z fio i sprawdzić, czy pamięć jest wystarczająco szybka, aby etcd działał dobrze. Teraz możesz sam to wypróbować, używając na przykład maszyn wirtualnych z pamięcią SSD IBM Cloud.

Źródło: www.habr.com

Dodaj komentarz