Tutoriel Linux

Cgroups Linux, sprawdź limity CPU i pamięci usługi

Débutant5 min de lecture

Usługa internetowa, która spowalnia, zabity worker bez wyraźnej wiadomości lub serwer, który zamienia pamięć, niekoniecznie wyczerpał całą pamięć RAM maszyny. Z systemd, limit na jednostce może wystarczyć, aby wyjaśnić objaw.

cgroups umożliwiają jądru Linuxa zliczanie, ograniczanie i priorytetyzowanie zasobów grupy procesów. Zanim dodasz pamięć lub zrestartujesz bez większego zastanowienia, sprawdź, co systemd stosuje do danej usługi.

Tux przed serwerami z wskaźnikiem zasobów CPU i pamięci
Cgroups i limity zasobów usługi Linux zarządzanej przez systemd.

Zobacz cgroup usługi

Na nowoczesnych dystrybucjach systemd umieszcza każdą usługę w jej własnym cgroup. Nie musisz ręcznie przenosić PID-ów, aby diagnozować klasyczną jednostkę, taką jak Nginx, PostgreSQL lub aplikację roboczą.

Rozpocznij od przeczytania stanu usługi i właściwości związanych z zasobami. Zamień nginx.service na rzeczywistą nazwę twojej jednostki.

systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec

ControlGroup daje ścieżkę zarządzaną przez systemd. MemoryCurrent pokazuje pamięć zliczoną dla jednostki w momencie odczytu. Jeśli MemoryMax wynosi infinity, systemd nie ustawił twardego limitu pamięci dla tej usługi.

Jeśli zaczynasz od PID, sprawdź jego cgroup w /proc. W cgroup v2 często zobaczysz linię w stylu 0::/system.slice/nginx.service.

pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup

Jeśli MainPID wynosi 0, usługa nie ma aktywnego głównego procesu. Wróć do systemctl status i journalctl, zamiast wyciągać wnioski z pustego PID.

Przeczytaj limity pamięci i CPU

MemoryMax to limit twardy. Jeśli cgroup osiągnie ten pułap, a jądro nie odzyska wystarczająco pamięci, proces z grupy może zostać zabity przez OOM killera.

MemoryHigh jest mniej brutalny. Jądro ogranicza alokacje i stara się odzyskać pamięć, gdy cgroup przekroczy ten próg. Aby ograniczyć usługę bez jej zburzenia przy pierwszym szczycie, często jest to lepsze pierwsze ustawienie niż MemoryMax.

CPUQuota ogranicza czas CPU dostępny dla usługi. CPUQuota=25% daje równowartość jednej czwartej logicznego rdzenia. Na maszynie z wieloma rdzeniami, CPUQuota=200% pozwala na użycie do dwóch rdzeni czasu CPU.

systemctl show nginx.service 
  -p MemoryCurrent -p MemoryMax -p MemoryHigh 
  -p CPUUsageNSec -p CPUQuotaPerSecUSec

Nie mieszaj kwoty z priorytetem. Kwota uniemożliwia usłudze przekroczenie ilości CPU. Priorytet, za pomocą nice lub CPUWeight, arbitralnie rozstrzyga głównie o konkurencji, gdy wiele zadań żąda CPU w tym samym czasie.

Znajdź źródło limitu

Limit może pochodzić z pliku dostarczonego przez pakiet, drop-in systemd lub lokalnie utworzonego override. Przeczytaj pełną konfigurację przed dokonaniem zmian w usłudze.

systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths

Plik w /etc/systemd/system/nginx.service.d/ zazwyczaj ma pierwszeństwo przed jednostką dostarczoną przez pakiet. Unikaj modyfikowania bezpośrednio plików w /usr/lib/systemd/system/ lub /lib/systemd/system/, ponieważ aktualizacja może je nadpisać.

Następnie sprawdź symptomy. Spowolniona usługa może również wynikać z wolnego zapytania SQL, zapełnionego dysku, pełnej kolejki lub błędu aplikacji.

journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'

Jeśli limity pozostają na infinity i dziennik jądra nie pokazuje żadnych zdarzeń pamięci, szukaj gdzie indziej, zanim dotkniesz cgroups: logi aplikacji, metryki dysku, opóźnienia sieciowe lub rzeczywiste zużycie procesu.

Testowanie bez dotykania usługi

Aby sprawdzić składnię lub zmierzyć efekt limitu, uruchom tymczasową jednostkę z systemd-run. Test nie zmienia Nginx, PostgreSQL ani twojej usługi biznesowej.

sudo systemd-run --unit=essai-limite-memoire 
  --property=MemoryMax=256M 
  --property=CPUQuota=25% 
  /usr/bin/bash -c 'sleep 300'

Następnie przeczytaj zastosowane właściwości. Dla CPUQuota=25% systemd może wyświetlić wartość równoważną 250ms na sekundę.

systemctl show essai-limite-memoire.service 
  -p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat essai-limite-memoire.service

Zatrzymaj jednostkę testową, gdy tylko skończysz. Z sleep zapomnienie jest niezbyt poważne, jednak ten odruch zapobiega niespodziankom, gdy test uruchamia prawdziwe polecenie.

sudo systemctl stop essai-limite-memoire.service

Zastosowanie override systemd

Kiedy dzienniki i pomiary potwierdzają, że limit ma sens, przejdź do override systemd. Poniższy przykład ustawia próg wysokiego na 800 MB, twardy limit na 1 GB i ogranicza usługę do równoważności jednego rdzenia CPU.

sudo systemctl edit mon-service.service

Dodawaj tylko niezbędne dyrektywy. Nie kopiuj tych wartości na produkcyjną usługę, nie obserwując jej normalnego zużycia i szczytów.

[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%

Przeładuj systemd, a następnie uruchom usługę ponownie tylko wtedy, gdy przerwa jest akceptowalna. Zdalnie, trzymaj otwartą drugą sesję SSH, gdy dotykasz krytycznego komponentu.

sudo systemctl daemon-reload
sudo systemctl restart mon-service.service
systemctl status mon-service.service --no-pager
systemctl show mon-service.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec

Jeśli usługa już nie startuje lub staje się zbyt wolna, usuń override ostrożnie. sudo systemctl revert mon-service.service usuwa lokalne overrides jednostki. Nie używaj tego, jeśli ten sam katalog zawiera inne ustawienia do zachowania.

Kontrole po zmianie

  • Sprawdź stan za pomocą systemctl is-active mon-service.service.
  • Przeczytaj MemoryCurrent, MemoryHigh, MemoryMax i CPUQuotaPerSecUSec po restarcie.
  • Obserwuj journalctl -u mon-service.service -b i dziennik jądra podczas szczytu obciążenia, który powodował problem.
  • Zmierz efekt po stronie aplikacji: czas reakcji, opóźnione zadania, kolejki, błędy użytkownika.
  • Zanotuj powód ustawienia, datę, przyjętą wartość i skorygowane objawy w swojej procedurze operacyjnej.

Cgroups chronią resztę maszyny i sprawiają, że limity są widoczne. Nie rozwiązują problemu z wyciekiem pamięci, zbyt kosztownym zapytaniem lub źle wymierzonym workerem. Jeśli pułap zostanie osiągnięty, zachowaj dziennik, zaobserwowane obciążenie i skonfigurowaną wartość, aby zdecydować między dostosowaniem limitu a korektą aplikacji.

Aby poszerzyć wiedzę, strona systemd.resource-control(5) szczegółowo opisuje każdą dyrektywę. Przewodnik Nice w Linuxie pomaga w doborze priorytetu CPU, gdy twardy limit nie jest odpowiedni.