Întrebarea sună aproape întotdeauna la fel: noaptea trecută site-ul răspundea în douăzeci de secunde, iar până dimineața totul s-a rezolvat de la sine. Nu mai este nimic de văzut — top răspunde pentru secunda curentă, în timp ce întrebarea privește ora trei noaptea. Mai jos: ce înseamnă cu adevărat cifrele de încărcare, care dintre ele trebuie citite în perechi și de ce o măsurătoare izolată induce în eroare mai des decât ajută.
Load average: trei numere și o neînțelegere frecventă
uptime
cat /proc/loadavg
nproc
Cele trei numere sunt medii pe un minut, cinci și cincisprezece minute. Nu se compară cu zero, ci cu numărul de nuclee pe care îl indică nproc. O valoare de 8 pe o mașină cu opt nuclee este încărcare plină, dar sănătoasă: există exact atâta muncă cât poate duce serverul. O valoare de 2 pe un VPS cu un singur nucleu este o coadă de două ori mai lungă decât capacitatea, iar fiecare cerere își așteaptă rândul.
Raportul dintre cele trei numere arată direcția. Valoarea pe un minut mult peste cea pe cincisprezece minute înseamnă că încărcarea crește chiar acum. Invers înseamnă că vârful a trecut și că vedeți doar coada lui.
Acum, neînțelegerea din cauza căreia aceste cifre sunt cel mai des citite greșit. Sub Linux, load average nu înseamnă „utilizarea procesorului”. Spre deosebire de alte sisteme Unix, Linux numără acolo nu doar procesele care rulează sau sunt gata de rulare, ci și pe cele aflate în starea D — somn neîntreruptibil. Adică cele care așteaptă discul sau un sistem de fișiere în rețea. De aici serverul cu un load de 12 și un procesor aproape inactiv: munca nu avansează, toată lumea stă la coadă.
Procesor sau disc
Separarea celor două cazuri este primul lucru care merită făcut:
vmstat 1 5
iostat -x 1 3
În ieșirea comenzii vmstat contează trei coloane. r arată câte procese stau la coadă pentru procesor, b câte sunt blocate în așteptarea intrărilor și ieșirilor, iar wa proporția de timp în care procesorul a stat inactiv, așteptând discul. Un wa constant peste 10–15 % cu valori modeste la us și sy înseamnă că serverul este limitat de disc: adăugarea de nuclee nu ajută, cele existente sunt oricum libere.
Care procese așteaptă se poate afla pe nume:
ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'
Un exemplu din propria practică. Cu configurația implicită, Suricata scrie vreo treizeci de tipuri de evenimente și nu configurează nicio rotație pentru ele — pe un server în producție asta a dat 15 GB de jurnale în două zile. Încărcarea nu se manifesta ca procesor ocupat, ci tocmai ca I/O wait: sistemul scria fără oprire, iar tot restul stătea la coadă în urma lui. Remediul nu este un plan mai mare, ci o listă mai scurtă de tipuri de evenimente și o rotație configurată.
Cazul invers, pur procesor și mult mai puțin evident. O pagină web apela apt sub utilizatorul cu care rulează PHP-FPM. Root păstrează o memorie cache binară în /var/cache/apt/pkgcache.bin — 70 MB pe o gazdă cu o duzină de depozite — și o mapează în memorie gratuit. Un utilizator obișnuit nu poate scrie în acel director și reconstruiește cache-ul la fiecare apel. Măsurat pe una și aceeași mașină: 0,01 secunde de timp de procesor ca root față de 4,2 secunde ca utilizator neprivilegiat. Aceeași comandă, o diferență de patru sute de ori, înmulțită cu fiecare afișare a paginii.
Concluzia din ambele cazuri este aceeași: încărcarea se măsoară, nu se ghicește. Cronometrarea separată a fiecărei comenzi suspecte durează o jumătate de oră și arată de obicei în altă parte decât cea din care a pornit bănuiala.
Memoria: free nu arată ceea ce pare
free -h
Coloana used spune în sine foarte puțin, iar coloana free induce de-a dreptul în eroare: Linux dă memoria nefolosită cache-ului de pagini și o returnează aplicațiilor la prima cerere. Coloana de citit este available — cât se poate ocupa fără a intra în swap. Un buff/cache mare nu este o problemă, ci semnul unui sistem care funcționează așa cum trebuie.
La swap nu contează valoarea de moment, ci forma. A urcat și a revenit la zero: a fost un vârf scurt. A urcat o dată și a rămas acolo: vârful a avut deja loc, pagini au fost evacuate și nimeni nu le aduce înapoi — serverul pare liniștit, deși la un moment dat memoria nu i-a ajuns. Dacă schimbul are loc chiar acum se vede în coloanele si și so din vmstat; valorile diferite de zero sunt acolo forma de încetinire pe care utilizatorii o simt cel mai tare.
Dacă în timpul căderii de noapte un proces pur și simplu a dispărut, explicația se află de obicei aici:
journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"
O linie de tipul Out of memory: Killed process 1234 (mysqld) lămurește lucrurile mai bine decât orice grafic: baza de date nu „a căzut singură”, a oprit-o nucleul pentru că s-a terminat memoria.
Cine o provoacă
ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10
O rezervă: %CPU din ps este o medie pe toată viața procesului, așa că un vârf scurt se pierde în lista aceea. Pentru el sunt necesare top sau pidstat 1 5, care măsoară pe un interval.
Când încărcarea devine o problemă de securitate
Un procesor la 100 % constant peste noapte, cu un proces cu nume fără înțeles și director de lucru în /tmp sau /dev/shm, este imaginea clasică a unui miner, nu a unui site care a crescut. Un vârf de trafic de intrare împreună cu creșterea scrierilor în jurnale înseamnă un atac asupra parolelor în desfășurare. Un volum de jurnale care sare brusc este de regulă o furtună de alarme false ale vreunui filtru.
Instrumentele de protecție însele formează o categorie aparte. Pe unul dintre serverele noastre încărcarea se menținea în jur de trei fără niciun vizitator, iar în fruntea listei ps după timpul de procesor acumulat nu stăteau nici site-ul, nici baza de date, ci CrowdSec, fail2ban, Falco și Suricata. Nu este o defecțiune și nici un motiv de a le opri, dar prețul protecției merită cunoscut în cifre: pe un VPS mic se simte.
La ce folosește observarea
Tot ce s-a spus mai sus răspunde la întrebarea „ce se întâmplă acum”. Întrebarea de dimineață — ce s-a întâmplat la ora trei noaptea — nu este acoperită de aceste comenzi: despre noaptea trecută nu există date dacă nimeni nu le-a înregistrat. Iar ridicarea unui Prometheus cu Grafana pentru un singur VPS este discutabilă, fiindcă stiva care observă ajunge mai grea decât serverul observat.
Este de ajuns un rând într-o bază de date la fiecare cinci minute și o pagină care desenează din el ultimele douăzeci și patru de ore: load average, utilizarea procesorului și separat I/O wait, memoria și swap-ul, citirile și scrierile pe disc, umplerea partiției, inodurile, descriptorii de fișiere, conexiunile. Pe o singură axă de timp, perechile se citesc cu ochiul liber: wa ridicat cu procesorul liniștit, swap care nu a revenit niciodată la zero, descriptori care se apropie de limită — viitoarea eroare too many open files devine vizibilă cu ore înainte să se producă. Cum arată toate acestea puse la un loc se vede pe pagina demonstrativă de mai jos.