Frågan lyder nästan alltid likadant: i natt tog det tjugo sekunder för webbplatsen att svara, och till morgonen hade allt rättat till sig av sig självt. Det finns inget kvar att titta på — top svarar för den aktuella sekunden, medan frågan gäller klockan tre på natten. Nedan följer vad belastningssiffrorna faktiskt betyder, vilka av dem som måste läsas parvis och varför en enstaka mätning vilseleder oftare än den hjälper.
Load average: tre tal och ett vanligt missförstånd
uptime
cat /proc/loadavg
nproc
De tre talen är medelvärden över en, fem och femton minuter. De ska inte jämföras med noll utan med antalet kärnor som nproc rapporterar. Värdet 8 på en maskin med åtta kärnor är full men sund belastning: det finns precis så mycket arbete som servern hinner med. Värdet 2 på en VPS med en kärna är en kö dubbelt så lång som kapaciteten, och varje förfrågan får vänta på sin tur.
Förhållandet mellan de tre talen visar riktningen. Enminutersvärdet klart över femtonminutersvärdet betyder att belastningen stiger just nu. Tvärtom betyder att toppen redan passerat och att du ser dess svans.
Så till missförståndet som förstör läsningen av de här siffrorna mer än något annat. Load average i Linux är inte ”processoranvändning”. Till skillnad från andra Unix-system räknar Linux in inte bara processer som kör eller är redo att köra, utan också sådana i tillstånd D — oavbrytbar sömn. Det vill säga väntan på disken eller på ett nätverksfilsystem. Därav servern med load 12 och en nästan sysslolös processor: arbetet går inte framåt, alla står i kö.
Processor eller disk
Att skilja de två fallen åt är det första som är värt att göra:
vmstat 1 5
iostat -x 1 3
I utdata från vmstat är det tre kolumner som räknas. r är hur många processer som köar till processorn, b hur många som är blockerade i väntan på in- och utmatning, och wa den andel av tiden som processorn stått sysslolös och väntat på disken. Ett wa som stadigt ligger över 10–15 % vid måttliga us och sy betyder att servern begränsas av disken: att lägga till kärnor hjälper inte, de som finns är redan lediga.
Vilka processer som väntar går att lista vid namn:
ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'
Ett exempel ur egen praktik. Med standardkonfigurationen skriver Suricata ett trettiotal händelsetyper och sätter inte upp någon rotation för dem — på en produktionsserver gav det 15 GB loggar på två dygn. Belastningen visade sig då inte som upptagen processor utan just som I/O wait: systemet skrev oavbrutet och allt annat stod i kö bakom. Botemedlet är inte ett större abonnemang utan en kortare lista över händelsetyper och en konfigurerad rotation.
Det omvända fallet, rent processorbundet och betydligt mindre uppenbart. En webbsida anropade apt som den användare PHP-FPM körs som. Root håller en binär cache i /var/cache/apt/pkgcache.bin — 70 MB på en värd med ett dussin förråd — och mappar in den i minnet utan kostnad. En vanlig användare får inte skriva i den katalogen och bygger om cachen från början vid varje anrop. Mätt på en och samma maskin: 0,01 sekunder processortid som root mot 4,2 sekunder som opriviligierad användare. Samma kommando, en skillnad på fyrahundra gånger, multiplicerad med varje sidvisning.
Slutsatsen av båda fallen är densamma: belastning ska mätas, inte gissas. Att ta tid på varje misstänkt kommando för sig tar en halvtimme och pekar för det mesta någon annanstans än dit misstanken gick från början.
Minnet: free visar inte det som det ser ut som
free -h
Kolumnen used säger i sig själv mycket lite, och kolumnen free är rentav vilseledande: Linux lämnar oanvänt minne till sidcachen och tar tillbaka det till program vid första begäran. Kolumnen att läsa är available — hur mycket som kan tas i anspråk utan att gå till swap. En stor buff/cache är inget problem utan tecknet på ett system som fungerar som avsett.
För swap är det inte det aktuella värdet som räknas utan formen. Upp och tillbaka till noll: det fanns en kort topp. Upp en gång och kvar där: toppen har redan varit, sidor har trängts ut och ingen hämtar tillbaka dem — servern ser lugn ut trots att minnet vid något tillfälle inte räckte. Om växlingen pågår just nu visas i kolumnerna si och so i vmstat; värden skilda från noll där är den form av tröghet som användare märker tydligast.
Om en process helt enkelt försvann under nattens svacka står förklaringen oftast här:
journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"
En rad som Out of memory: Killed process 1234 (mysqld) avgör saken bättre än något diagram: databasen ”föll inte omkull av sig själv”, kärnan stoppade den för att minnet tog slut.
Vem som orsakar det
ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10
En reservation: %CPU i ps är ett medelvärde över processens hela livstid, så en kort topp försvinner i den listan. För den behövs top eller pidstat 1 5, som mäter över ett intervall.
När belastning blir en säkerhetsfråga
Jämna 100 % processor nattetid, med en process som har ett intetsägande namn och arbetskatalog i /tmp eller /dev/shm, är den klassiska bilden av en miner och inte av en webbplats som vuxit. En topp i inkommande trafik tillsammans med ökad skrivning till loggarna är en pågående lösenordsattack. En loggvolym som plötsligt skjuter i höjden är i regel en storm av falska larm från något filter.
Skyddsverktygen själva är en kategori för sig. På en av våra servrar låg belastningen kring tre utan en enda besökare, och överst i ps efter ackumulerad processortid stod varken webbplatsen eller databasen utan CrowdSec, fail2ban, Falco och Suricata. Det är varken ett fel eller ett skäl att stänga av dem, men priset för skyddet är värt att känna till i siffror: på en liten VPS märks det.
Vad iakttagelsen är till för
Allt ovanstående besvarar frågan ”vad händer nu”. Morgonens fråga — vad hände klockan tre i natt — täcks inte av de här kommandona: om natten som gått finns inga data om ingen har spelat in dem. Och att sätta upp Prometheus och Grafana för en enda VPS är tveksamt, eftersom den observerande stacken blir tyngre än servern som observeras.
Det räcker med en rad i en databas var femte minut och en sida som ritar det senaste dygnet ur den: load average, processoranvändning och I/O wait var för sig, minne och swap, läsning och skrivning mot disk, partitionens fyllnadsgrad, inoder, filbeskrivare, anslutningar. På en gemensam tidsaxel går paren att läsa med blotta ögat: högt wa med en lugn processor, swap som aldrig gick tillbaka till noll, beskrivare nära gränsen — det kommande felet too many open files blir synligt timmar innan det inträffar. Hur det ser ut sammanställt visar demosidan nedan.