Przekład artykułu przygotowany przed rozpoczęciem kursu .

Cyklicznie pojawiają się pytania dotyczące rekomendacji Gluster w sprawie konfiguracji jądra oraz czy jest to konieczne.
Taka konieczność występuje rzadko. W większości obciążeń jądro działa bardzo dobrze. Choć jest i druga strona. Historycznie jądro Linux chętnie wykorzystuje dużą ilość pamięci, jeśli ma taką możliwość, w tym do buforowania jako podstawowego sposobu na zwiększenie wydajności.
W większości przypadków działa to doskonale, lecz przy dużym obciążeniu może prowadzić do problemów.
Posiadamy duże doświadczenie w pracy z systemami, które intensywnie wykorzystują pamięć, takimi jak CAD, EDA i podobnymi, które zaczynały działać wolno przy wysokim obciążeniu. Czasami napotykaliśmy problemy w Gluster. Uważnie obserwując przez kilka dni zużycie pamięci i czas oczekiwania na dyski, zaobserwowaliśmy ich przeciążenie, ogromne iowait, błędy jądra (kernel oops), zawieszenia itd.
Ten artykuł jest wynikiem wielu eksperymentów związanych z konfiguracją parametrów przeprowadzonych w różnych sytuacjach. Dzięki tym parametrom nie tylko poprawiła się ogólna responsywność, ale także znacznie ustabilizowała się praca klastra.
W przypadku konfiguracji pamięci należy przede wszystkim zwrócić uwagę na podsystem pamięci wirtualnej (VM, virtual memory), który ma wiele opcji, które mogą wprowadzić w zakłopotanie.
vm.swappiness
Parametr vm.swappiness określa, jak bardzo jądro korzysta z swapu w porównaniu do pamięci operacyjnej. W kodzie źródłowym definiowany jest również jako „tendency to steal mapped memory” (skłonność do kradzieży pamięci mapowanej). Wysoka wartość swappiness oznacza, że jądro będzie bardziej skłonne do wyładowania mapowanych stron. Niska wartość swappiness oznacza odwrotność: jądro będzie mniej wyładować strony z pamięci. Innymi słowy, im wyższa wartość vm.swappiness, tym więcej system będzie korzystał z swapu.
Duże korzystanie z swapu jest niepożądane, ponieważ ogromne bloki danych są ładowane i wyładowywane z pamięci operacyjnej. Wiele osób twierdzi, że wartość swapiness powinna być wysoka, ale z mojego doświadczenia wynika, że zwiększenie wydajności osiąga się ustawiając ją na „0”.
Więcej informacji można znaleźć tutaj —
Jednakże te ustawienia należy stosować ostrożnie i tylko po przetestowaniu konkretnej aplikacji. Dla aplikacji o dużym obciążeniu strumieniowym ten parametr należy ustawić na „0”. Ustawienie na „0” poprawia responsywność systemu.
vm.vfs_cache_pressure
Ten parametr kontroluje pamięć używaną przez jądro do buforowania obiektów katalogów i deskryptorów indeksów (dentry i inode).
Przy domyślnej wartości 100 jądro będzie próbować zwolnić pamięć podręczną dentry i inode „sprawiedliwie” wobec pagecache i swapcache. Zmniejszenie vfs_cache_pressure powoduje, że jądro zachowuje pamięci podręczne dentry i inode. Gdy wartość wynosi „0”, jądro nigdy nie będzie oczyszczać pamięci podręcznej dentry i inode z powodu niedoboru pamięci (memory pressure), co może łatwo prowadzić do błędu out-of-memory. Zwiększenie vfs_cache_pressure powyżej 100 powoduje, że jądro priorytetowo traktuje usuwanie dentry i inode.
Przy użyciu GlusterFS wielu użytkowników z dużą ilością danych i wieloma małymi plikami może łatwo używać znaczącej ilości pamięci RAM na serwerze z powodu buforowania inode/dentry, co może prowadzić do spadku wydajności, ponieważ jądro musi przetwarzać struktury danych w systemie z 40 GB pamięci. Ustawienie tego parametru powyżej 100 pomogło wielu użytkownikom osiągnąć bardziej sprawiedliwe buforowanie i poprawić responsywność jądra.
vm.dirty_background_ratio i vm.dirty_ratio
Pierwszy parametr (vm.dirty_background_ratio) określa procent pamięci z brudnymi stronami, przy osiągnięciu którego należy rozpocząć tło zrzucanie brudnych stron na dysk. Dopóki ten procent nie zostanie osiągnięty, strony nie są zrzucane na dysk. A gdy zrzut się zaczyna, odbywa się to w tle, nie przerywając działających procesów.
Drugi parametr (vm.dirty_ratio) określa procent pamięci, który może być zajęty przez brudne strony, zanim rozpocznie się wymuszone zwolnienie (forced flash). Po osiągnięciu tego progu wszystkie procesy stają się synchroniczne (blokowane), a ich kontynuacja pracy jest wstrzymywana, dopóki żądana operacja wejścia/wyjścia nie zostanie faktycznie zakończona i dane nie trafią na dysk. Przy intensywnym wejściu/wyjściu prowadzi to do problemów, ponieważ brak jest buforowania danych, a wszystkie procesy zajmujące się wejściem/wyjściem są blokowane w oczekiwaniu na wykonanie operacji. Prowadzi to do dużej liczby zablokowanych procesów, wysokiego obciążenia, niestabilnej pracy systemu i słabej wydajności.
Zmniejszenie wartości tych parametrów prowadzi do częstszego zwalniania danych na dysk i ograniczania ich przechowywania w RAM. Może to pomóc systemom z dużą ilością pamięci, w których normalne jest zwalnianie na dysk pamięci podręcznej stron o rozmiarze 45-90 GB, co prowadzi do ogromnego czasu oczekiwania dla aplikacji frontendowych, obniżając ogólną responsywność i interaktywność.
„1” > /proc/sys/vm/pagecache
Pamięć podręczna stron (page cache) to pamięć podręczna, w której przechowywane są dane plików i programów wykonywalnych, a więc strony z faktyczną zawartością plików lub urządzeń blokowych. Ta pamięć podręczna jest używana do zmniejszenia liczby odczytów z dysku. Wartość „1” oznacza, że dla pamięci podręcznej używanych jest 1% RAM, a operacji odczytu z dysku będzie więcej niż z RAM. Nie ma potrzeby zmieniania tego parametru, ale jeśli jesteś paranoicznie nastawiony na kontrolę nad pamięcią podręczną stron, możesz z niego skorzystać.
„deadline” > /sys/block/sdc/queue/scheduler
Planista wejścia/wyjścia (I/O scheduler) to komponent jądra Linux, który obsługuje kolejki odczytów i zapisów. Teoretycznie dla inteligentnego kontrolera RAID lepiej jest używać „noop”, ponieważ Linux nic nie wie o fizycznej geometrii dysku, więc efektywniej jest pozwolić kontrolerowi, który dobrze zna geometrię dysku, na jak najszybsze przetworzenie żądania. Jednak wydaje się, że „deadline” poprawia wydajność. Więcej informacji o planistach można znaleźć w dokumentacji dotyczącej kodu źródłowego jądra Linux: linux/Documentation/block/*osched.txt. A także zauważyłem wzrost przepustowości odczytu podczas mieszanych operacji (wiele operacji zapisów).
„256” > /sys/block/sdc/queue/nr_requests
Liczba zapytań wejścia/wyjścia w buforze przed ich przekazaniem do planera. Rozmiar wewnętrznej kolejki niektórych kontrolerów (queue_depth) jest większy niż nr_requests planera wejścia/wyjścia, przez co planer ma małe szanse na prawidłowe priorytetyzowanie i wykonanie scalania zapytań. W przypadku plannerów deadline i CFQ lepiej, gdy nr_requests jest 2 razy większy od wewnętrznej kolejki kontrolera. Scalanie i reorganizacja zapytań pomagają planowi być bardziej responsywnym przy dużym obciążeniu.
echo «16» > /proc/sys/vm/page-cluster
Parametr page-cluster zarządza liczbą stron, które są zapisywane w swapie za jednym razem. W powyższym przykładzie wartość ustawia się na „16” w zgodzie z rozmiarem stripa (stripe size) RAID wynoszącym 64 KB. Nie ma to sensu przy swappiness = 0, ale jeśli ustawiłeś swappiness na 10 lub 20, użycie tej wartości pomoże Ci, gdy rozmiar stripa RAID wynosi 64 KB.
blockdev —setra 4096 /dev/<devname> (-sdb, hdc lub dev_mapper)
Domyślne ustawienia urządzeń blokowych dla wielu kontrolerów RAID często prowadzą do słabej wydajności. Dodanie powyższej opcji ustawia wstępne odczyty na 4096 * 512-bajtowych sektorów. Przynajmniej w przypadku operacji strumieniowych zwiększa to prędkość, napełniając podręczną pamięć podręczną dysku dzięki wstępnym odczytom w okresie, w którym jądro przygotowuje wejście/wyjście. W pamięci podręcznej mogą znajdować się dane, które zostaną zażądane przy następnym odczycie. Zbyt duże wstępne odczyty mogą zabić losowe wejście/wyjście dla dużych plików, jeśli wykorzystuje ono potencjalnie przydatny czas dysku lub ładuje dane poza cach'em.
Oto kilka dodatkowych zaleceń na poziomie systemu plików. Ale nie zostały one jeszcze przetestowane. Upewnij się, że twój system plików zna rozmiar stripa i liczbę dysków w macierzy. Na przykład, że jest to macierz raid5 z rozmiarem stripa 64K z sześcioma dyskami (w rzeczywistości z pięcioma, ponieważ jeden dysk jest używany do parzystości). Te zalecenia są oparte na teoretycznych założeniach i zebrane z różnych blogów/artyków ekspertów RAID.
-> ext4 fs, 5 dysków, 64K stripe, jednostki w blokach 4K
mkfs -text4 -E stride=$((64/4))
-> xfs, 5 dysków, 64K stripe, jednostki w sektorach 512-bajtowych
mkfs -txfs -d sunit=$((64*2)) -d swidth=$((5*64*2))W przypadku dużych plików można rozważyć zwiększenie wymienionych powyżej rozmiarów pasm.
UWAGA! Wszystko, co zostało opisane powyżej, jest skrajnie subiektywne dla niektórych typów aplikacji. Ten artykuł nie gwarantuje poprawy wydajności bez wcześniejszego przetestowania odpowiednich aplikacji przez użytkownika. Należy go stosować tylko w przypadku potrzeby poprawy ogólnej responsywności systemu lub gdy rozwiązuje aktualne problemy.
Dodatkowe materiały:
Czytaj więcej
Źródło: habr.com
