
Krótka historia o fio i etcd
Wydajność klastra w dużej mierze zależy od wydajności jego magazynu. etcd eksportuje niektóre metryki do , aby dostarczyć potrzebne informacje o wydajności magazynu. Na przykład metrykę wal_fsync_duration_seconds. : aby magazyn uznano za wystarczająco szybki, 99. percentyl tej metryki powinien być mniejszy niż 10 ms. Jeśli planujesz uruchomić klaster etcd na maszynach Linux i chcesz ocenić, czy twoje magazyn (np. SSD) jest wystarczająco szybki, możesz użyć — popularne narzędzie do testowania operacji wejścia/wyjścia. Uruchom następującą komendę, gdzie test-data to katalog pod punktem montowania magazynu:
fio --rw=write --ioengine=sync --fdatasync=1 --directory=test-data --size=22m --bs=2300 --name=mytestWystarczy spojrzeć na wyniki i sprawdzić, czy 99. percentyl trwania jest mniejszy niż 10 ms. Jeśli tak, masz wystarczająco szybki magazyn. Oto przykład wyników:
sync (usec): min=534, max=15766, avg=1273.08, stdev=1084.70
percentyle sync (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 wartości parametrów —size i —bs do naszego konkretnego scenariusza. Aby uzyskać użyteczny wynik z fio, wprowadź swoje wartości. Skąd je wziąć? Czytaj, .
- Podczas testowania cały ruch wejścia/wyjścia pochodzi z fio. W rzeczywistym scenariuszu w magazynie prawdopodobnie będą również inne żądania zapisu, oprócz tych związanych z wal_fsync_duration_seconds. Dodatkowy ruch zwiększy wartość wal_fsync_duration_seconds. Więc jeśli 99. percentyl ledwie osiąga 10 ms, twoje magazyn nie jest wystarczająco szybki.
- Wybierz wersję nie niższą niż 3.5 (wcześniejsze nie pokazują percentyli trwania fdatasync).
- Powyżej pokazano tylko fragment wyników z fio.
Długa historia o fio i etcd
Czym jest WAL w etcd
Zazwyczaj bazy danych używają ; etcd również to wykorzystuje. Nie będziemy szczegółowo omawiać dziennika zapisu wstecznego (write-ahead log, WAL). Wystarczy wiedzieć, że każdy członek klastra etcd prowadzi go w trwałym magazynie. etcd zapisuje każdą operację z parami klucz-wartość (np. aktualizację) w WAL, zanim zastosuje je w magazynie. Jeśli między zrzutami jeden z członków magazynu awaryjnie się wyłączy i uruchomi ponownie, może lokalnie odzyskać transakcje od momentu ostatniego zrzutu na podstawie zawartości WAL.
Kiedy klient dodaje klucz do magazynu par klucz-wartość lub aktualizuje wartość istniejącego klucza, etcd zapisuje informację o tej operacji w WAL, który jest zwykłym plikiem w trwałym magazynie. Zanim etcd przejdzie do dalszego przetwarzania, MUSI być całkowicie pewny, że zapis w WAL rzeczywiście się odbył. W systemie Linux nie wystarczy jedno wywołanie systemowe, , ponieważ rzeczywisty zapis do fizycznego magazynu może być opóźniony. Na przykład Linux może przez pewien czas przechowywać zapis WAL w pamięci podręcznej jądra (np. w pamięci podręcznej stron). Aby dane zostały dokładnie zapisane w trwałym magazynie, wymagane jest wywołanie systemowe fdatasync po zapisie, i etcd właśnie to wykorzystuje (jak można zobaczyć w wynikach działania , gdzie 8 to 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) = 0Niestety, zapis do trwałego magazynu nie odbywa się natychmiast. Jeśli wywołanie fdatasync działa wolno, wydajność systemu etcd spada. , że magazyn jest uważany za wystarczająco szybki, jeśli w 99. percentylu wywołań fdatasync przy zapisie do pliku WAL zajmuje mniej niż 10 ms. Istnieją również inne przydatne metryki dla magazynu, ale w tym poście mówimy tylko o tej metryce.
Ocena magazynu z użyciem fio
Jeśli chcesz ocenić, czy twoje przechowywanie danych nadaje się do etcd, użyj fio — bardzo popularnego narzędzia do testowania obciążenia I/O. Należy pamiętać, że operacje dyskowe mogą być bardzo różnorodne: synchroniczne i asynchroniczne, mnóstwo klas wywołań systemowych itd. W związku z tym fio jest dość skomplikowane w użyciu. Ma wiele parametrów, a różne kombinacje ich wartości generują zupełnie różne obciążenia I/O. Aby uzyskać adekwatne wyniki dla etcd, należy upewnić się, że testowe obciążenie zapisu z fio jest maksymalnie zbliżone do rzeczywistego obciążenia zapisu w etcd przy zapisie plików WAL.
W związku z tym fio powinno przynajmniej generować obciążenie w formie serii sekwencyjnych operacji zapisu do pliku, każda zapis będzie się składała z wywołania systemowego , po którym następuje wywołanie systemowe fdatasync. Dla sekwencyjnych operacji zapisu fio potrzebuje parametru —rw=write. Aby przy zapisie fio używało wywołania systemowego write, a nie , warto określić parametr —ioengine=sync. Na koniec, aby po każdym zapisie wywoływano fdatasync, należy dodać parametr —fdatasync=1. Dwa inne parametry w tym przykładzie (—size i —bs) zależą od konkretnego scenariusza. W następnym rozdziale opowiemy, jak je skonfigurować.
Dlaczego to właśnie fio i jak nauczyliśmy się je konfigurować
W tym poście opisujemy rzeczywisty przypadek. Mieliśmy klaster v1.13, który monitorowaliśmy za pomocą Prometheus. etcd v3.2.24 był umieszczony na SSD. Metryki dotyczące etcd pokazywały zbyt wysokie opóźnienia dla fdatasync, nawet gdy klaster nic nie robił. Metryki były dziwne i nie do końca wiedzieliśmy, co one oznaczają. Klaster składał się z maszyn wirtualnych, musieliśmy zrozumieć, gdzie leży problem: w fizycznych SSD czy w warstwie wirtualizacji. Co więcej, często wprowadzaliśmy zmiany w konfiguracji sprzętu i oprogramowania, potrzebowaliśmy sposobu na ocenę ich efektów. Mogliśmy uruchomić etcd w każdej konfiguracji i patrzeć na metryki Prometheus, ale to było zbyt uciążliwe. Szukaliśmy wystarczająco prostego sposobu na ocenę konkretnej konfiguracji. Chcieliśmy sprawdzić, czy poprawnie rozumiemy metryki Prometheus z etcd.
Ale w tym celu należało rozwiązać dwa problemy. Po pierwsze, jak wygląda obciążenie we/wy, które etcd generuje przy zapisie do WAL? Jakie wywołania systemowe są używane? Jaki jest rozmiar zapisów? Po drugie, jeśli odpowiemy na te pytania, jak odtworzyć podobne obciążenie robocze za pomocą fio? Nie zapominaj, że fio to bardzo elastyczne narzędzie z wieloma parametrami. Rozwiązaliśmy oba problemy jednym podejściem — za pomocą poleceń. i . lsof wyświetla wszystkie uchwyty plików używane przez proces i powiązane z nimi pliki. A za pomocą strace można zbadać już uruchomiony proces lub uruchomić nowy proces i go zbadać. strace wyprowadza wszystkie wywołania systemowe z badanego procesu (i jego procesów potomnych). To ostatnie jest bardzo ważne, ponieważ etcd stosuje właśnie takie podejście.
Na początku użyliśmy strace, aby zbadać serwer etcd dla Kubernetes, gdy klaster nie był obciążony. Zauważyliśmy, że prawie wszystkie zapisy WAL miały podobny rozmiar: 2200–2400 bajtów. Dlatego w poleceniu na początku postu wskazaliśmy parametr —bs=2300 (bs oznacza rozmiar w bajtach dla każdego zapisu fio). Zauważ, że rozmiar zapisu etcd zależy od wersji etcd, dostawy, wartości parametrów itp. i wpływa na czas trwania fdatasync. Jeśli masz podobny scenariusz, zbadaj swoje procesy etcd za pomocą strace, aby poznać dokładne liczby.
Następnie, aby dobrze zobrazować działania w systemie plików etcd, uruchomiliśmy go z strace i z parametrami -ffttT. Próbowaliśmy zbadać procesy potomne i zapisać dane wyjściowe każdego z nich w osobnym pliku, a ponadto uzyskać szczegółowe raporty dotyczące rozpoczęcia i czasu trwania każdego wywołania systemowego. Użyliśmy lsof, aby potwierdzić naszą analizę danych wyjściowych strace i zobaczyć, który uchwyt pliku był używany do jakich celów. W ten sposób za pomocą strace uzyskaliśmy wyniki przedstawione powyżej. Statystyki dotyczące czasu synchronizacji potwierdziły, że wskaźnik wal_fsync_duration_seconds z etcd odpowiada wywołaniom fdatasync z uchwytami plików WAL.
Zbadaliśmy dokumentację fio i wybraliśmy parametry dla naszego scenariusza, aby fio wygenerował obciążenie podobne do etcd. Sprawdziliśmy również wywołania systemowe i ich czas trwania, uruchamiając fio z strace, w podobny sposób jak etcd.
Starannie dobraliśmy znaczenie parametru —size, który reprezentuje całkowite obciążenie wejścia-wyjścia od fio. W naszym przypadku jest to łączna liczba bajtów zapisywanych w magazynie. Okazało się, że jest to bezpośrednio proporcjonalne do liczby wywołań systemowych write (i fdatasync). Dla określonej wartości bs liczba wywołań fdatasync = size/bs. Ponieważ interesował nas percentyl, musieliśmy mieć wystarczającą liczbę próbek dla wiarygodności, i obliczyliśmy, że wystarczy nam 10^4 (co daje 22 mebibajty). Jeśli —size jest mniejsze, może wystąpić duża zmienność (na przykład kilka wywołań fdatasync trwa dłużej niż zwykle i wpływa na 99-ty percentyl).
Spróbuj samodzielnie
Pokazaliśmy, jak używać fio i sprawdzić, czy prędkość magazynu jest wystarczająca dla wysokiej wydajności etcd. Teraz możesz wypróbować to w praktyce samodzielnie, korzystając na przykład z maszyn wirtualnych z magazynem SSD w .
Źródło: habr.com
