Zbliżenie na sprzęt serwerowy w nowoczesnym centrum danych
Źródło: Pexels | Autor: panumas nikhomkhai
Rate this post

Serwer „zwalnia”, użytkownicy zgłaszają timeouty, a Ty widzisz tylko jedno: coś jest nie tak. W panelu hostingu świeci „wysokie obciążenie”, aplikacja działa raz szybciej, raz wolniej, a w logach… chaos. Co robisz jako początkujący administrator Linuxa: restart usługi? ubijasz proces? zwiększasz zasoby? To naturalne odruchy, ale często kończą się jednym — problem wraca, tylko trudniej go potem wyjaśnić.

Monitoring wydajności Linuxa dla początkujących administratorów nie musi oznaczać stawiania dużych platform i tygodni konfiguracji. Kluczem jest triage jak na dyżurze: szybkie rozpoznanie, na jaki zasób wszyscy czekają (CPU, RAM, dysk, sieć, limity środowiska), zebranie „dowodów” i dopiero wtedy decyzja, czy to temat na optymalizację, skalowanie, czy zwykłe usunięcie usterki.

Realne pytania, które zwykle masz w głowie w tej sytuacji:

  • Jak w 10–15 minut rozpoznać, czy to CPU, pamięć, I/O dysku czy sieć?
  • Co oznacza load average i dlaczego bywa wysokie, gdy CPU „się nudzi”?
  • Jak odróżnić brak RAM od „Linux używa cache, więc wygląda na pełny”?
  • Jak czytać iowait/latencję dysku i nie mylić „disk usage 100%” z problemem I/O?
  • Co w VM/chmurze znaczy steal time i kiedy winny jest host?
  • Jakie komendy zebrać do ticketu, żeby nie wracać 10 razy po brakujące dane?

Niżej dostajesz schemat diagnostyczny oraz praktyczne komendy, które działają na większości dystrybucji. Zamiast „listy 50 narzędzi” — decyzje oparte o sygnały.

Frazy pomocnicze (SEO): load average a CPU, iowait i latencja dysku, vmstat interpretacja, iostat -x util await, swap i page faults, ss -s retransmisje, steal time w VM, systemd-cgtop limity cgroups, pakiet dowodów z serwera, sysstat sar, D-state procesy, df vs problemy I/O

Nawigacja:

Serwer „zwalnia” i nikt nie wie dlaczego — ustawienie kontekstu incydentu

Mini-scenka z życia: timeouty, rosnący load, „raz działa, raz nie”

Typowy obrazek: aplikacja webowa łapie timeouty, w monitoringu aplikacyjnym rośnie czas odpowiedzi, a na serwerze pojawia się rosnące load average. Czasem CPU jest na 90–100%, ale równie często CPU wygląda „w porządku”, a mimo to wszystko jest ociężałe. To moment, w którym najłatwiej wpaść w pułapkę: potraktować objaw jak przyczynę.

Zadaj sobie jedno pytanie: czy system wykonuje pracę wolno, czy raczej nie może jej wykonywać, bo na coś czeka? „Czekanie” w Linuxie najczęściej oznacza dysk (I/O), sieć (np. DNS, NFS), blokady w jądrze, limity CPU w kontenerze albo CPU „zabrane” przez hosta wirtualizacji.

Pytania diagnostyczne jak na dyżurze: co się zmieniło i kiedy?

Zanim odpalisz narzędzia, zbierz kontekst. To skraca diagnostykę bardziej niż kolejna komenda. Zapytaj (siebie albo zespół): co się zmieniło w ostatniej godzinie/dniu? Deploy? backup? rotacja logów? zmiana konfiguracji bazy? wzrost ruchu? migracja na inny storage?

Drugie pytanie: czy problem jest stały, czy w skokach? Jeśli „w skokach”, to znaczy, że gdzieś jest proces okresowy (cron, backup, indeksowanie, raporty, batch) albo zasób współdzielony (storage/network), który ma gorsze okna.

Trzecie: czy dotyczy wszystkich usług, czy jednej? Jeśli tylko jednej, szukasz w jej procesach i zależnościach (DB, DNS, API zewnętrzne). Jeśli wszystkiego naraz — bardziej prawdopodobne jest wąskie gardło hosta (RAM/dysk/CPU/limity).

Objaw vs przyczyna: dlaczego load bywa mylący

Wysoki load average nie mówi „CPU jest na 100%”. Mówi raczej: jest kolejka zadań, które chcą CPU albo są nieprzerywalnie zablokowane (np. na I/O). Dlatego load może rosnąć przy wysokim iowait i jednocześnie sporym idle CPU. Klucz to znalezienie odpowiedzi: kto na kogo czeka?

W praktyce „monitoring wydajności Linuxa” zaczyna się od umiejętności interpretacji kilku metryk i szybkiego rozpoznania wzorca. Narzędzia są środkiem, nie celem.

Pierwsze 10–15 minut triage — kolejność kroków, żeby nie błądzić

Schemat działań: rób to w tej kolejności

Jeśli masz tylko kwadrans, trzymaj się kolejności. Minimalizuje to ryzyko, że utkniesz w analizie jednego obszaru, gdy problem leży gdzie indziej.

  1. Ustal czas i kontekst: kiedy zaczęło się psuć, czy to VM/kontener, czy były zmiany.
  2. Sprawdź ogólny stan: uptime, load, procesy w skrócie.
  3. CPU: czy to realne zużycie, czy throttling/steal.
  4. Pamięć: RAM, „available”, swap, oznaki presji.
  5. Dysk: najpierw miejsce (df), potem I/O (latencja/util).
  6. Sieć: błędy, dropy, retransmisje, kolejki połączeń.
  7. Logi: kernel i usługi w oknie czasowym incydentu.
  8. Zrób snapshot „dowodów” do ticketu/notatnika.

Minimalny zestaw komend na start i po co każda

Nie potrzebujesz od razu niczego egzotycznego. Poniższe polecenia występują praktycznie wszędzie albo są dostępne po doinstalowaniu jednego pakietu.

  • Ogólny rzut oka: uptime, top lub htop
  • Pamięć: free -h, vmstat 1
  • Miejsce na dysku: df -h, du -xhd1 /var | sort -h (gdy coś rośnie)
  • Wydajność I/O: iostat -x 1 (pakiet sysstat)
  • Sieć: ss -s, ip -s link
  • Logi: journalctl -p warning..alert -S -1h, dmesg -T | tail -n 80

Uwaga praktyczna: jeśli nie masz iostat, mpstat, pidstat — doinstaluj sysstat (np. apt install sysstat, dnf install sysstat). To zestaw podstawowy dla monitoringu wydajności Linuxa na CLI.

Co notować, żeby nie diagnozować „na pamięć”

Gdy presja rośnie, łatwo zapomnieć, co było „przed restartem”. A restart bardzo często kasuje ślady (cache, kolejki, stany procesów). Zapisuj:

  • timestamp (czas pobrania danych) i strefę czasową, jeśli działasz w środowisku międzynarodowym,
  • host/instancja (nazwa, IP, identyfikator w chmurze),
  • czy to VM/kontener oraz ile ma vCPU/RAM (na ile to możliwe),
  • top 3 procesy: PID, %CPU, %MEM, stan (R/D/S),
  • load average, swap, iowait/steal, najważniejsze sygnały z iostat i ss.

Pierwszy bezpieczny ruch: snapshot zanim „naprawiasz”

Masz pokusę: „ubiję proces i zobaczę”. Jeśli to system produkcyjny, najpierw zrób mały snapshot informacji. Wystarczy wkleić output do notatnika albo ticketu. To często jedyna szansa, by po fakcie odpowiedzieć na pytanie: dlaczego to się stało? oraz czy to wróci?

Objaw: wysoki load, a CPU nie jest „zawalony” — pułapka i jej przyczyny

Load average a użycie CPU: jak nie wyciągnąć złych wniosków

Widzisz: uptime pokazuje load 10, 15, 20… a masz tylko 4 vCPU. Naturalna myśl: CPU przeciążone. Ale potem w top widzisz idle 40–60%. To sygnał, że część procesów stoi w kolejce, ale nie dlatego, że brakuje cykli CPU.

Praktyczna interpretacja:

  • Jeśli load rośnie i jednocześnie %idle spada do zera — realne nasycenie CPU (albo limit/throttling).
  • Jeśli load rośnie, ale %idle wciąż jest wysokie — procesy czekają na coś innego (często I/O), albo są w stanie nieprzerywalnym.

To jeden z najważniejszych nawyków w monitoringu wydajności Linuxa: zawsze koreluj load z tym, co pokazuje scheduler CPU.

D-state, iowait i kolejki: co dokładnie rośnie?

Gdy proces w Linuxie wchodzi w stan D (uninterruptible sleep), najczęściej czeka na I/O (np. dysk, storage sieciowy). Wtedy potrafi „pompować” load average mimo tego, że CPU nie jest zajęte. Jak to sprawdzić szybko?

1) Sprawdź w top:

  • wa (iowait) — jeśli rośnie, CPU „czeka na dysk”.
  • liczbę procesów w stanie D (w top zwykle widać podsumowanie stanów).

2) Potwierdź w vmstat 1:

  • r — ile procesów czeka na CPU (run queue),
  • b — ile procesów jest zablokowanych (często I/O),
  • wa — procent czasu CPU w iowait.

3) Wypisz procesy w D-state:

ps -eo pid,stat,comm,wchan:30 | awk '$2 ~ /D/ {print}'

wchan potrafi podpowiedzieć, na czym proces „wisi” (nie zawsze czytelnie, ale często daje trop).

Dwa typowe źródła: dysk/FS i „niewinne” zależności jak DNS

Najczęstszy powód: storage. Może to być lokalny dysk z dużą latencją, macierz z przeciążeniem, wolny snapshot, a czasem po prostu proces, który robi intensywny zapis (np. logi, backup, kompresja, przebudowa indeksów). Wtedy load rośnie, bo coraz więcej wątków próbuje coś odczytać/zapisać.

Drugi częsty przypadek, mniej oczywisty: sieć jako zależność blokująca (np. DNS, NFS). Aplikacja czeka na odpowiedź z resolvera DNS albo na zdalny udział plików, a wątki akumulują się. Load rośnie, a CPU nadal ma wolne cykle, bo „czekanie” nie wymaga CPU.

Bezpieczne działanie w trakcie incydentu: zmniejsz kolejkę, nie zwiększaj jej

Jeśli wąskim gardłem jest I/O, to dokładanie workerów (np. zwiększenie liczby procesów aplikacji) często pogarsza sprawę: więcej równoległych operacji I/O = większa kolejka = większa latencja. Lepszy pierwszy ruch to:

  • potwierdzić problem I/O (iostat -x),
  • sprawdzić, czy jakiś proces nie generuje masowego zapisu (logi, backup),
  • tymczasowo ograniczyć najbardziej agresywny proces (np. priorytet I/O przez ionice),
  • sprawdzić logi kernela pod kątem błędów dysku/FS.

Objaw: 100% CPU albo throttling — kiedy to CPU, a kiedy limit/VM

CPU „zjedzone” przez procesy vs CPU, którego nie dostajesz

Jeżeli CPU jest na 100%, pierwsze pytanie brzmi: czy CPU jest zajęte pracą, czy CPU jest ograniczone? To rozróżnienie jest kluczowe w VM i kontenerach.

W top patrz na rozkład:

  • us (user): aplikacje spalają CPU (kod, kompresja, szyfrowanie).
  • sy (system): kernel intensywnie pracuje (I/O, sieć, sterowniki, wiele przerwań).
  • st (steal): w VM host zabiera Ci czas CPU — Ty chcesz liczyć, ale hypervisor daje CPU komuś innemu.

Jeśli st rośnie, problem może nie leżeć w Twoich procesach, tylko w przeciążonym hoście, złej klasie instancji, oversubscription albo limitach platformy.

Jak namierzyć winowajcę: top/htop, a gdy trzeba — pidstat

Na start wystarczy:

  • top: sortowanie po %CPU, obserwacja przez 20–60 sekund (czy to stałe, czy skoki).
  • htop: drzewo procesów, łatwe podejrzenie wątków i per-core (czy jeden rdzeń jest „przybity”, a reszta się nudzi?).

Gdy chcesz potwierdzenia bez „skakania” w top, dołóż pidstat (sysstat). Pytanie kontrolne: czy jeden PID stale pożera CPU, czy kilka procesów po trochu, ale bez przerwy? To robi różnicę w działaniach.

  • pidstat -u 1 — CPU per proces w czasie (łatwo zobaczyć, kto jest konsekwentny, a kto tylko „pikował”),
  • pidstat -t -u 1 -p <PID> — CPU per wątek (przydatne, gdy aplikacja ma jeden gorący wątek i cały serwer wygląda na „100%”, bo jeden core jest dociśnięty),
  • pidstat -d 1 — gdy podejrzewasz, że to jednak I/O, a nie czyste CPU.

Jeżeli proces wygląda na „user CPU” (us wysoko), zapytaj: co on dokładnie liczy? Czasem to normalne (np. kompresja, szyfrowanie), a czasem regresja po wdrożeniu albo pętla po błędnych danych. Jeżeli dominuje sy, sprawdź przerwania i sieć: mpstat -P ALL 1 (czy jeden CPU obsługuje większość IRQ), do tego sar -n DEV 1 lub chociaż ip -s link (czy nie rośnie licznik błędów/dropów).

Throttling i limity to osobna historia. W kontenerach najczęściej chodzi o cgroup: aplikacja widzi „100%”, ale to 100% przydzielonego limitu, nie całej maszyny. Jak brzmi Twoje pytanie: czy proces zjada CPU hosta, czy tylko odbija się od limitu? Szybki trop:

  • CPU quota w cgroup v2: cat /sys/fs/cgroup/cpu.max (np. 200000 100000 oznacza limit ~2 vCPU),
  • statystyki throttlingu: cat /sys/fs/cgroup/cpu.stat (pola typu nr_throttled, throttled_usec),
  • w VM: top i mpstat 1 — rosnący st to klasyk, gdy host jest przeładowany.

Dwa krótkie scenariusze z życia: (1) po deployu rośnie CPU w jednym procesie aplikacji, bo debug logging serializuje requesty i mieli JSON-y — us wysoko, w pidstat widać stabilny „winowajca”; (2) wszystko wygląda jak „CPU 100%”, ale to kontener z limitem 1 vCPU na maszynie 16 vCPU — dopiero cpu.stat pokazuje, że wątki są systematycznie throttle’owane, a zwiększenie limitu rozwiązuje problem bez jakiejkolwiek optymalizacji kodu.

Objaw: brak pamięci, swap mieli, aplikacje dostają timeouty — przyczyny i potwierdzenia

Jak odróżnić „zużycie pamięci” od realnej presji

Najpierw ustal, czy to faktycznie presja, czy tylko cache. Zadaj sobie pytanie: czy system aktywnie odzyskuje pamięć i spowalnia, czy po prostu trzyma dane w cache, bo może? W praktyce patrz na free -h: interesuje Cię available, nie samo used. Niskie available i rosnący swap to zwykle realny problem.

Drugi szybki wskaźnik: vmstat 1. Jeśli widzisz rosnące si/so (swap in/out) i jednocześnie skacze wa albo aplikacje łapią timeouty, to nie jest „niewinny cache”, tylko maszyny brakuje RAM albo ktoś go wycieka. Do tego dochodzi nieprzyjemny efekt domina: swap na wolnym dysku potrafi zamienić serwer w „zawieszkę”, mimo że CPU wygląda umiarkowanie.

Co potwierdzi, że to już „presja pamięci”, a nie zwykły cache?

Zadaj sobie jedno proste pytanie: czy system musi co chwilę „przekładać” strony pamięci, żeby przeżyć? Jeśli tak, zobaczysz to w metrykach i w zachowaniu usług (lagi, timeouty, procesy zamierające na sekundę–kilka).

Minimalny zestaw sprawdzeń, który zwykle daje jasny obraz:

  • free -h — interesują Cię: available oraz Swap used (czy swap realnie rośnie w czasie).
  • vmstat 1 — patrz na si/so (swap in/out) i r (run queue). Gdy si/so nie są zerowe przez dłuższą chwilę, system „mieli”.
  • sar -B 1 (sysstat) — jeśli masz: pgscan/pgsteal i wzmożone skanowanie to sygnał, że kernel agresywnie odzyskuje pamięć.
  • dmesg -T | tail lub journalctl -k -n 200 --no-pager — czy pojawiają się wpisy o OOM (Out of memory) albo o ubijaniu procesu.

Jeśli masz objawy „serwer staje”, a w metrykach swap wchodzi w grę, nie interpretuj tego jak zwykłego wzrostu zużycia RAM. To już problem wydajnościowy, nie kosmetyka.

Kto zjada RAM: szybkie wskazanie podejrzanych bez zgadywania

Chcesz odpowiedzi w 30 sekund, a nie polowania po katalogach? Zacznij od procesu, a dopiero potem schodź niżej. Dwie komendy zazwyczaj wystarczą, żeby wytypować sprawców:

  • ps aux --sort=-%mem | head — na start: top procesów po %RAM.
  • smem -tk (jeśli masz) — pokazuje PSS/USS, lepiej oddaje realny koszt pamięci przy współdzielonych bibliotekach.

Gdy nie masz smem, a potrzebujesz „dlaczego ten proces jest tak wielki?”, podejrzyj mapy pamięci:

  • pmap -x <PID> | tail -n 20 — szybki rzut oka na największe segmenty,
  • cat /proc/<PID>/status | egrep 'VmRSS|VmSize|RssAnon|RssFile|Threads' — czy to realny RSS, czy wirtualna przestrzeń.

Pomocne pytanie diagnostyczne: czy to jeden proces rośnie bez końca (wyciek), czy wiele procesów robi to samo (skalowanie/konfiguracja)? Przy wycieku zwykle widzisz „jednego grubasa”, przy złej konfiguracji — stadko podobnych procesów o podobnym profilu.

OOM killer i „magiczne restarty”: jak nie przegapić najważniejszego sygnału

Klasyczny scenariusz: aplikacja co jakiś czas „sama się restartuje”, a Ty widzisz tylko przerwę w logach. To często nie jest restart aplikacji, tylko kernel ubija proces, bo brakuje pamięci. Najpierw potwierdź fakt, dopiero potem szukaj winnych.

Szybkie tropy:

  • journalctl -k --since "30 min ago" | egrep -i 'oom|killed process|out of memory'
  • journalctl --since "30 min ago" | egrep -i 'oom|killed|segfault' (czasem loguje to też systemd/unit)

Jeśli OOM występuje, „zabijanie procesu ręcznie” bywa działaniem pozornym. Bez poprawy limitów, konfiguracji albo ilości RAM wróci przy kolejnym piku.

Swap: kiedy pomaga, a kiedy maskuje problem

Swap potrafi uratować maszynę przed natychmiastowym OOM, ale potrafi też utopić wydajność. Kluczowe pytanie brzmi: czy swap jest używany sporadycznie, czy system stale do niego ucieka?

Sprawdź dwie rzeczy:

  • swapon --show — czy swap w ogóle istnieje, jaki ma rozmiar i priorytet,
  • sar -W 1 (sysstat) albo vmstat 1 — czy swapowanie jest ciągłe.

Jeśli swapowanie jest ciągłe, pierwsze „bezpieczne” ruchy to zwykle:

  • zatrzymać/ograniczyć proces, który skokowo alokuje pamięć (jeśli to backup, raport, zadanie batch — ogranicz równoległość),
  • sprawdzić limity (VM/kontener/cgroup) — bo aplikacja może mieć mniej RAM, niż zakładasz,
  • zebrać dowody (kto rośnie, kiedy, po jakiej zmianie), zamiast od razu kręcić vm.swappiness.

Zmiana swappiness bywa kusząca, ale nie jest „naprawą” braku RAM. Jeśli baza danych lub JVM nie mieści się w pamięci, to i tak wrócisz do punktu wyjścia.

Objaw: dysk „mieli”, rośnie iowait, usługi odpowiadają coraz wolniej

Jak odróżnić „dużo I/O” od „wysokiej latencji”

W praktyce mniej boli wysoki throughput, bardziej boli latencja. Pytanie kontrolne: czy dysk jest zajęty, bo robi dużo małych operacji, czy dlatego, że pojedyncza operacja trwa długo?

Najprostsze potwierdzenie daje iostat -x 1 (pakiet sysstat). Patrz na:

  • %util — czy urządzenie jest blisko 100% przez dłużej (nasycenie),
  • await (oraz r_await/w_await) — czy latencja rośnie,
  • avgqu-sz — czy kolejka się wydłuża (objaw korka),
  • r/s, w/s — czy to wiele operacji na sekundę, czy mało, ale wolno.

Jeśli await jest wysokie, a %util też wysoko — masz realny wąskie gardło I/O. Jeśli %util niskie, a aplikacja „czeka na dysk”, możliwe, że problem jest wyżej: FS, blokady, NFS, warstwa wirtualizacji, throttling, a czasem po prostu inny dysk (np. inny wolumen) niż ten, który obserwujesz.

Kto generuje zapis/odczyt: iotop, pidstat i „zwykłe” lsof

Gdy widzisz objawy I/O, pojawia się naturalna pokusa: „to na pewno baza danych”. Zanim to powiesz na głos, sprawdź, kto faktycznie robi I/O.

  • iotop -oPa — pokazuje procesy, które aktualnie robią I/O (wymaga uprawnień roota, zależnie od systemu).
  • pidstat -d 1 — stabilny obraz aktywności I/O w czasie (kto generuje odczyt/zapis).
  • lsof +L1 — czy masz procesy piszące do plików już usuniętych (typowy „znikający” problem z miejscem i I/O: log zrotowany, ale proces nadal trzyma uchwyt).

Krótki przykład z praktyki: rotacja logów działa, plik znika z katalogu, a miejsce na dysku nie wraca. Serwer zwalnia, bo dysk dobija do 100% zajętości i metadane dostają w kość. lsof +L1 od razu pokazuje PID-y, które dalej zapisują do „(deleted)”. Rozwiązanie bywa prozaiczne: restart usługi albo kill -HUP, żeby przeładowała logi.

Gdy kończy się miejsce: to nie tylko „brak przestrzeni”, to też spadek wydajności

Pełny lub prawie pełny dysk potrafi wywołać objawy jak przy awarii: spowolnienia, błędy zapisu, problemy z DB. Najpierw potwierdź:

  • df -h — zajętość,
  • df -i — inody (szczególnie na katalogach z milionami małych plików),
  • du -xhd1 /var | sort -h — gdzie urosło (zatrzymaj się na jednym filesystemie, -x pomaga).

Jeśli dysk jest zapchany, „czyszczenie na oślep” potrafi zrobić większy bałagan niż pożytek. Najczęstsze pułapki:

  • kasowanie plików, do których proces nadal pisze (miejsce nie wróci, a aplikacja dalej będzie mielić),
  • usuwanie „losowych” plików z /var/lib bez zrozumienia, co to jest (łatwy sposób na uszkodzenie danych),
  • przenoszenie ciężkich katalogów między filesystemami bez przerwy w usługach (w trakcie przenosin potrafisz dobić I/O jeszcze bardziej).

Objaw: sieć wygląda „normalnie”, a użytkownicy mają timeouty i lagi

Czy to przepustowość, czy jakość połączeń?

Sieć rzadko jest problemem w sensie „braku Mbps”. Częściej chodzi o RTT, gubienie pakietów, retransmisje, kolejki lub DNS. Zadaj sobie pytanie: czy ruch jest duży, czy połączenia są słabe?

Na start weź trzy proste źródła prawdy:

  • ss -s — ile masz połączeń, ile w jakich stanach (np. dużo SYN-SENT, TIME-WAIT, ESTAB),
  • ss -ti — informacje o TCP: retransmisje, RTT, cwnd (widać, czy TCP „cierpi”),
  • ip -s link — błędy interfejsu, dropy, overruns (to często bardziej mówi prawdę niż „ping działa”).

Jeżeli rosną dropy albo błędy na interfejsie, to nie jest temat na „tuning aplikacji”. To jest temat na warstwę niżej (sterownik, wirtualny switch, MTU, przeciążenie hosta, kolejki).

DNS jako wąskie gardło: tani test, który często oszczędza godziny

Gdy aplikacja ma timeouty do „różnych” usług, a CPU/RAM/dysk wyglądają akceptowalnie, DNS bywa winowajcą. Pytanie diagnostyczne: czy lagi dotyczą nowych połączeń / pierwszego requestu?

Szybkie sprawdzenia:

  • resolvectl status (systemd-resolved) albo sprawdzenie /etc/resolv.conf — jaki resolver i czy jest sensowny,
  • getent hosts nazwa — jak szybko system rozwiązuje nazwę (to testuje ścieżkę systemową, nie tylko „dig do 8.8.8.8”),
  • dig +tries=1 +time=1 nazwa — czy masz opóźnienia i czy pojawiają się time-outy.

Jeśli DNS jest wolny lub niestabilny, aplikacja „stoi” mimo braku presji na CPU. A Ty widzisz tylko „dziwne” timeouty w logach. Wtedy najpierw stabilizujesz resolvery/caching, a dopiero potem grzebiesz w kodzie.

Paczka dowodów do incydentu: co zebrać, zanim cokolwiek zmienisz

Snapshot, który ma sens: mało, ale konkretnie

Jeśli masz zgłosić problem dalej (albo wrócić do niego jutro), przyda Ci się zestaw danych, który odpowiada na pytanie: co było wąskim gardłem i kiedy? Zbieraj rzeczy, które da się porównać w czasie i które nie zależą od „pamięci admina”.

Prosty zestaw do skopiowania do notatnika lub ticketa (w chwili, gdy „muli”):

  • date; uptime
  • top -b -n 1 | head -n 40
  • free -h
  • vmstat 1 5
  • iostat -x 1 3 (jeśli sysstat jest dostępny)
  • ss -s oraz ss -ti | head
  • df -h; df -i
  • journalctl -k -n 200 --no-pager (albo przynajmniej filtr na OOM/dysk)

Jeśli to VM/kontener, dorzuć jeszcze:

  • VM: mpstat 1 3 (czy rośnie st),
  • kontener/cgroups: cat /sys/fs/cgroup/cpu.max, cat /sys/fs/cgroup/memory.max, cat /sys/fs/cgroup/cpu.stat.

Czego unikać w trakcie „gaszenia”

Największy błąd w triage to robienie zmian, które psują obserwowalność i mieszają przyczynę ze skutkiem. Jeśli musisz działać, działaj tak, żeby nadal dało się odpowiedzieć na pytanie „dlaczego”.

  • Nie zwiększaj na ślepo liczby workerów, gdy podejrzewasz I/O — dołożysz kolejkę i latencję.
  • Nie „czyść dysku” losowo — najpierw znajdź źródło wzrostu i procesy trzymające usunięte pliki (lsof +L1).
  • Nie wyłączaj swapu w panice — jeśli system jest pod presją, możesz natychmiast wywołać OOM i uciąć usługę całkiem.

Nie restartuj „bo może pomoże” bez zrzutu stanu: przy restartach giną kolejki, liczniki i kontekst w logach. Jeśli już musisz ubić proces, zrób to świadomie: najpierw sprawdź, czy to on jest źródłem presji (pidstat/iotop), potem zbierz minimalny snapshot, a dopiero na końcu działaj.

Unikaj też „napraw” typu zmiana sysctl w ciemno. Pytanie kontrolne: co chcesz poprawić i jak to zmierzysz za 5 minut? Bez miary i punktu odniesienia łatwo skończyć z konfiguracją, która maskuje problem w jednym miejscu, a psuje w innym.

Jeśli masz do wyboru kilka ruchów ratunkowych, wybierz ten, który jest odwracalny i ma mały promień rażenia. Przykład: limitowanie jednego zadania batchowego (cgroups/renice/ionice) bywa bezpieczniejsze niż „dokładanie RAM” albo zmiana parametrów JVM w czasie pożaru. I znowu: czy wiesz, które SLA ratujesz — API, kolejkę, bazę, a może tylko panel admina?

Najczęstszy błąd przy takich incydentach? Gonienie za „najgłośniejszym” wykresem zamiast za zasobem, który faktycznie blokuje pracę. Load, 100% CPU, pełny dysk — to tylko wskaźniki. Dopiero korelacja z opóźnieniami, kolejkami i procesami daje odpowiedź, co dusi system.

Kiedy problem siedzi „obok” zasobów: limity, cgroups i wirtualizacja

Zdarza się, że CPU/RAM/dysk wyglądają „w miarę”, a użytkownicy i tak widzą opóźnienia. Pytanie diagnostyczne: czy to jest goły Linux na serwerze, czy proces siedzi w VM albo kontenerze? W tych światach łatwo pomylić „masz zasoby” z „ktoś Cię ogranicza”.

VM: steal time — CPU jest, ale nie dla Ciebie

Jeśli jesteś w VM, szczególnie na współdzielonym hoście, obserwuj steal (czas „ukradziony” przez hypervisor). Objaw: load rośnie, aplikacja laguje, a top nie pokazuje ekstremów w user/system. CPU niby wolne… tylko że Twój VM nie dostaje slotów.

Potwierdzenie jest proste:

  • mpstat -P ALL 1 5 — patrz na kolumnę %steal (skrótowo st),
  • top — na części dystrybucji zobaczysz st w nagłówku CPU.

Co z tym zrobić? Jeśli st jest zauważalny w trakcie incydentu, „optymalizacja aplikacji” zwykle nic nie da. Często jedyne sensowne ruchy to: zmiana rozmiaru instancji, przeniesienie na mniej obciążony host, albo ograniczenie zadań batch w godzinach szczytu. Pytanie kontrolne: czy masz wpływ na warstwę infrastruktury, czy musisz eskalować do dostawcy?

Kontenery i cgroups: proces dostaje OOM, mimo że RAM „jest wolny”

W kontenerach typowy klasyk: free -h na hoście wygląda dobrze, a aplikacja w kontenerze jest ubijana przez OOM. Dlaczego? Bo limit pamięci jest na poziomie cgroups, a nie całej maszyny.

Sprawdź limit i zużycie wprost:

  • cat /sys/fs/cgroup/memory.max — limit (wartość max oznacza „bez limitu”),
  • cat /sys/fs/cgroup/memory.current — bieżące zużycie,
  • cat /sys/fs/cgroup/memory.events — czy rośnie oom/oom_kill,
  • cat /sys/fs/cgroup/cpu.stat — czy rośnie nr_throttled (CPU throttling).

Jeżeli widzisz throttling CPU albo OOM na cgroups, przestań „tłumaczyć” to metrykami hosta. To inny świat. W praktyce rozwiązania są trzy: dać większy limit, zmniejszyć apetyt procesu (np. cache, worker count), albo rozdzielić ciężkie zadania na osobne kontenery.

„System jest wolny”, ale nie widać winnego procesu — jak szukać dalej

Masz moment, kiedy top nie krzyczy, a jednak wszystko czeka. Co wtedy? Zamiast błądzić, złap dwie rzeczy: na co procesy czekają i czy kernel nie sygnalizuje problemu.

Stany procesów i kolejki: czy to run queue, czy D-state?

Wysoki load bez wysokiego CPU często oznacza procesy w stanie D (uninterruptible sleep) — zwykle I/O. Pytanie: czy w procesach widzisz dużo „D”?

  • ps -eo state,pid,comm,wchan:32 | egrep '^(D|R)' | head — szybki podgląd „kto w D/R” i na jakim wait channel,
  • vmstat 1 5r (run queue) i b (blocked); dużo b to często I/O,
  • cat /proc/pressure/{cpu,io,memory} — PSI pokaże, czy system realnie traci czas na presję danego zasobu (świetne, jeśli jest dostępne).

Jeśli PSI dla IO rośnie, a CPU PSI jest niskie, masz mocny sygnał: ludzie widzą lagi nie dlatego, że „brakuje mocy”, tylko dlatego, że zadania stoją w korku na wejściu/wyjściu.

Kernel i logi: szukaj słów-kluczy, nie opowieści

Gdy podejrzewasz, że problem nie jest „w aplikacji”, często prawda jest w logach jądra. Nie czytaj wszystkiego — filtruj po symptomach. Co chcesz znaleźć: OOM, reset urządzenia, błędy FS, time-outy, problemy z siecią.

  • journalctl -k --since "30 min ago" --no-pager
  • dmesg -T | egrep -i 'oom|kill|ext4|xfs|nvme|blk|reset|timeout|link is down|call trace'

Jeśli pojawiają się komunikaty typu reset kontrolera, błędy NVMe, problemy z ext4/xfs, to „zwiększenie limitu workerów” jest jak dolewanie paliwa do silnika, który właśnie traci olej. Najpierw stabilność.

Od triage do stałego monitoringu: minimalny poziom, który realnie pomaga

Ręczne komendy są świetne w incydencie, ale po trzeciej powtórce ten sam problem zaczyna kosztować. Pytanie: czy chcesz tylko gasić pożary, czy chcesz dostawać sygnał, zanim użytkownicy zadzwonią?

sysstat jako „czarna skrzynka”: sar i historia, której brakuje w 3:00

Najtańszy upgrade to włączenie zbierania podstawowych metryk przez sysstat. To nie jest wielka platforma, a daje historię: CPU, pamięć, dysk, sieć — w rytmie minut. W kryzysie liczy się to, że możesz cofnąć czas.

Jeśli pakiet jest dostępny:

  • Debian/Ubuntu: apt install sysstat i włączenie zbierania (zależnie od dystrybucji: /etc/default/sysstat),
  • RHEL/CentOS/Alma/Rocky: dnf install sysstat i systemctl enable --now sysstat (nazwy usług mogą się różnić).

Najbardziej użyteczne komendy sar w praktyce:

  • sar -q — load, run queue (czyli „ile czeka”),
  • sar -u — CPU z rozbiciem (szukaj %iowait, a w VM także %steal),
  • sar -r — pamięć,
  • sar -b lub sar -d — I/O (zależnie od wersji),
  • sar -n DEV — sieć per interfejs.

Jeśli masz tylko jedną rzecz wynieść: historia metryk jest ważniejsza niż „idealny wykres”. Bez historii łatwo pomylić pik z trendem.

Progi alertów, które nie są „na oko”

Alerty mają sens, jeśli odpowiadają na pytanie: czy użytkownicy za chwilę to odczują? Kilka praktycznych sygnałów, które zwykle mają lepszą korelację z bólem niż „CPU 80%”:

  • IO wait rośnie i utrzymuje się + jednocześnie rośnie latencja dysku (iostat await),
  • swap-in/swap-out zaczyna pracować (w vmstat kolumny si/so) — to często początek „mulenia”,
  • PSI dla memory/io pokazuje stałą presję (jeśli dostępne),
  • dropy/błędy na interfejsie (ip -s link),
  • disk usage przekracza sensowny próg wcześniej, zanim dobijesz do 100% (bo „prawie pełny” to też problem).

Pułapka: ustawienie progów zbyt agresywnie i zrobienie z monitoringu generatora szumu. Jeśli dostajesz alerty non stop, przestajesz je czytać — i przegapisz ten właściwy.

Decyzje naprawcze: co wybierać, żeby nie pogorszyć sytuacji

Masz już trop. Teraz pojawia się pokusa „szybkiej poprawki”. Zatrzymaj się na jednym pytaniu: czy rozwiązanie usuwa przyczynę, czy tylko przenosi koszt w inne miejsce?

CPU: ogranicz źródło, zanim dołożysz rdzenie

Jeśli to realne CPU (wysokie us/sy, mało wa), pierwsze bezpieczne kroki to zwykle:

  • sprawdzenie, czy to jeden proces/endpoint/job (profil „kto zjada CPU” w top/htop + pidstat -u 1),
  • tymczasowe ograniczenie batcha: nice/renice, a gdy walczysz o IO — także ionice,
  • w VM/kontenerze: weryfikacja limitów i throttlingu zamiast „skalowania w ciemno”.

Dodanie workerów do aplikacji CPU-bound często tylko zwiększa przełączanie kontekstu i pogarsza tail latency. Jeśli nie widzisz, że kolejka requestów się skraca po zwiększeniu równoległości — to znak, że idziesz w złą stronę.

Pamięć: swap jako objaw, nie wróg

Gdy swap pracuje, pytanie brzmi: czy to chwilowy pik, czy stała presja? Jeśli stała, to zwykle nie „zły swap”, tylko zbyt mało RAM, wyciek pamięci albo cache rosnący bez kontroli (czasem w aplikacji, czasem w stronie systemowej).

  • Potwierdź presję: vmstat 1 5 (si/so), free -h, PSI memory.
  • Znajdź winnego: ps aux --sort=-rss | head (prosty start) i ewentualnie smem jeśli masz.

Najgorszy ruch „na szybko”: wyłączenie swapu, gdy system już walczy. To często kończy się OOM w najmniej kontrolowanym momencie.

Dysk: redukuj latencję, nie tylko „%util”

Jeżeli dysk jest wąskim gardłem, wygrywa ten, kto umie zmniejszyć liczbę synchronizacji i skoków, a nie tylko „zbić procent użycia”. Czasem wystarczy:

  • ograniczyć proces, który robi ciężki zapis (ionice -c2 -n7 -p PID),
  • przenieść batch poza peak,
  • sprawdzić, czy logi nie lecą na ten sam wolumen co baza (konflikt wzorców I/O).

Pułapka: „zoptymalizuję bazę” bez potwierdzenia, że to ona generuje I/O. Najpierw pidstat -d/iotop, potem decyzja.

Sieć: mniej tuningu, więcej dowodów

Gdy sieć „nie dowozi”, zmiany sysctl potrafią zamaskować problem. Lepiej zebrać twarde sygnały:

  • ss -ti — retransmisje/RTT rosną?
  • ip -s link — błędy i dropy?
  • ethtool -S eth0 — jeśli masz dostęp, statystyki sterownika często pokazują prawdę szybciej niż aplikacja.

Typowy scenariusz z praktyki: aplikacja „czasem” timeoutuje, a w logach brak sensownych wyjątków. ss -ti pokazuje retransmisje, a ip -s link dropy na interfejsie w VM. Wtedy temat jest po stronie hosta/overlay, nie w kodzie.

Najczęstszy błąd na finiszu: leczenie wykresu zamiast wąskiego gardła

Wykresy kuszą, bo są proste. „CPU wysokie” wygląda jednoznacznie, „load skacze” też. A potem okazuje się, że CPU było skutkiem: procesy kręciły się, bo czekały na dysk albo DNS. Jeśli po Twojej zmianie metryka „ładnie spadła”, ale czasy odpowiedzi się nie poprawiły — wróć do pytania: kto na kogo czeka i gdzie jest kolejka? To ona zwykle zdradza prawdziwego winnego.

Najczęściej zadawane pytania (FAQ)

Jak w 10–15 minut sprawdzić, czy serwer zwalnia przez CPU, RAM, dysk czy sieć?

Masz presję czasu i chcesz tylko wiedzieć: na co wszyscy czekają? Zacznij od szybkiego „triage”, zamiast grzebać w jednym miejscu na ślepo. Najpierw ustal: czy problem dotyczy jednej usługi czy całego hosta — i czy to VM/kontener.

Minimalny zestaw, który zwykle wystarcza na pierwszy obraz:

  • Ogólnie: uptime, top/htop
  • RAM/presja pamięci: free -h, vmstat 1
  • Dysk (I/O, nie tylko miejsce): df -h, iostat -x 1 (sysstat)
  • Sieć: ss -s, ip -s link
  • Logi w oknie incydentu: journalctl -p warning..alert -S -1h, dmesg -T | tail -n 80

Jedno pytanie prowadzące: czy CPU faktycznie pracuje, czy raczej „stoi”, bo czeka na dysk/sieć/limity?

Dlaczego load average jest wysokie, mimo że CPU ma dużo idle?

Load average nie oznacza „CPU jest na 100%”. To liczba zadań, które chcą być wykonane (na CPU) albo są w stanie nieprzerywalnym (często czekają na I/O). Dlatego możesz mieć load 15 przy 4 vCPU i jednocześnie sporo %idle.

Sprawdź korelację:

  • Jeśli load rośnie i %idle spada do zera → realne nasycenie CPU albo throttling/limit.
  • Jeśli load rośnie, a %idle nadal wysokie → szukaj blokad: I/O (iowait), D-state, storage sieciowe, DNS/NFS, limity cgroups.

Najczęstszy błąd: „load wysoki, to dołóż CPU”. Najpierw odpowiedz sobie: kto jest w kolejce i na co czeka?

Jak rozpoznać, że procesy wiszą na dysku (iowait/D-state), a nie na CPU?

Gdy system „mul i timeoutuje”, a CPU wygląda na spokojne, to często dysk albo storage sieciowe. Zacznij od top: patrz na wa (iowait) i liczbę procesów w stanie D.

Potem potwierdź w dwóch krokach:

  • vmstat 1b (blocked) i wa (iowait); wysokie b to częsty trop I/O.
  • iostat -x 1 → szukaj wysokiego await i %util (oraz kolejek). To mówi o latencji i „zatkaniu” urządzenia.

Chcesz szybki konkret? Wypisz D-state: ps -eo pid,stat,comm,wchan:30 | awk '$2 ~ /D/ {print}'. Jeśli nagle widzisz tam procesy aplikacji lub bazy, to zwykle nie „CPU za małe”, tylko I/O przestaje dowozić.

Jak odróżnić „brak RAM” od sytuacji, gdzie Linux używa cache i wygląda jakby pamięć była pełna?

Patrz na available, nie na samą „used”. W free -h kolumna available mówi, ile pamięci da się realnie odzyskać bez bólu (cache/buffers też się liczą).

Co jest podejrzane?

  • Available blisko zera i rosnące użycie swap → presja pamięci.
  • W vmstat 1 rosną si/so (swap in/out) albo system zaczyna „szarpać” responsywność → często thrashing.

Praktyczne pytanie: czy problem zaczął się po wdrożeniu/zmianie konfiguracji (więcej workerów, większy cache aplikacji)? Jeśli tak, winny bywa RAM zanim ktokolwiek spojrzy na CPU.

Co oznacza „disk usage 100%” i czemu to nie zawsze problem z miejscem na dysku?

Dwa różne „100%” ludzie mylą non stop. df -h pokazuje zajętość miejsca (brak miejsca = operacje zapisu i logowanie potrafią się wykoleić). Natomiast iostat -x pokazuje obciążenie urządzenia I/O (np. %util blisko 100% + wysokie await), czyli „dysk nie wyrabia z operacjami”.

Jak to rozdzielić bez filozofii?

  • Jeśli df -h pokazuje 95–100% → szukaj, co urosło (du -xhd1 /var | sort -h), rotacje logów, backupy, tmp.
  • Jeśli df jest OK, ale iostat -x 1 pokazuje wysokie await → problem z latencją I/O (storage, kolejki, RAID, EBS, NFS).

Najgorsza decyzja na skróty: „wyczyściłem miejsce, więc będzie szybciej”. Miejsce to jedno, wydajność I/O to drugie.

Co to jest steal time w VM i kiedy winny jest host, a nie mój serwer?

Jeśli działasz na wirtualce, CPU może wyglądać na „dostępne”, ale realnie host zabiera Ci czas procesora. W metrykach pojawia się wtedy steal (często w top lub mpstat). To sygnał: Twoja VM chciała wykonać pracę, ale hypervisor w tym czasie obsłużył innych.

Jak to interpretować praktycznie?

  • Wysoki steal + spadek wydajności aplikacji, mimo że „u Ciebie” procesy nie wyglądają dramatycznie → podejrzenie oversellingu hosta lub problemu po stronie platformy.
  • Steal skacze w określonych oknach → możliwe, że sąsiedzi na hoście mają batch/backup, a Ty dostajesz resztki CPU.

Zanim zaczniesz „optymalizować kod”, zadaj sobie pytanie: czy to na pewno Twój problem, czy limit środowiska?

Jakie komendy zebrać do ticketu, żeby nie wracać 10 razy po brakujące dane?

Najpierw snapshot, potem „naprawianie”. Restart usługi często usuwa ślady (kolejki, stany D, objawy presji pamięci), a później zostajesz z „wydaje mi się”. Zbierz paczkę danych z timestampem i kontekstem (host/instancja, VM/kontener, zasoby).

Dobry minimalny „pakiet dowodów” wygląda tak:

  • date; uptime
  • Najważniejsze punkty

  • Najpierw triage, potem akcja: zamiast restartować na ślepo, odpowiedz sobie „na jaki zasób wszyscy czekają?” — CPU, RAM, dysk, sieć czy limity środowiska (VM/kontener).
  • Wysoki load average to nie synonim „CPU na 100%”: load rośnie także wtedy, gdy procesy stoją w kolejce albo wiszą w stanie nieprzerywalnym (np. I/O), więc CPU może mieć sporo idle.
  • Zanim odpalisz narzędzia, złap kontekst incydentu: co się zmieniło (deploy, backup, rotacja logów, migracja storage), czy problem jest ciągły czy „w skokach”, i czy dotyczy jednej usługi czy całego hosta — te trzy pytania często ustawiają kierunek diagnozy.
  • Trzymaj się kolejności w pierwszych 10–15 minutach: ogólny stan (uptime/top) → CPU (realne zużycie vs steal/throttling) → pamięć (available, swap, presja) → dysk (df, a potem latencja/util) → sieć (błędy, dropy, retransmisje) → logi (kernel/usługi w oknie zdarzenia).
  • RAM „pełny” nie zawsze znaczy problem: Linux używa cache, więc patrz na „available”, zachowanie swap i sygnały presji z vmstat (np. skoki page faults), a nie tylko na goły „used”.
  • „Disk usage 100%” i problem I/O to dwie różne rzeczy: miejsce sprawdzasz df/du, a wydajność ocenisz po iostat -x (util/await, iowait) — typowy wzorzec to rosnący load i timeouty przy procesach czekających na dysk.