Spørgsmålet lyder næsten altid ens: i nat var webstedet tyve sekunder om at svare, og til morgen var alt bragt i orden af sig selv. Der er ikke mere at kigge på — top svarer for det aktuelle sekund, mens spørgsmålet handler om klokken tre om natten. Herunder: hvad belastningstallene faktisk betyder, hvilke af dem der skal læses parvis, og hvorfor en enkelt måling vildleder oftere, end den hjælper.
Load average: tre tal og en udbredt misforståelse
uptime
cat /proc/loadavg
nproc
De tre tal er gennemsnit over et, fem og femten minutter. De skal ikke sammenlignes med nul, men med antallet af kerner, som nproc oplyser. Værdien 8 på en maskine med otte kerner er fuld, men sund belastning: der er præcis så meget arbejde, som serveren kan nå. Værdien 2 på en VPS med én kerne er en kø, der er dobbelt så lang som kapaciteten, og hver forespørgsel venter på tur.
Forholdet mellem de tre tal viser retningen. Etminutsværdien tydeligt over femtenminutsværdien betyder, at belastningen stiger lige nu. Omvendt betyder det, at toppen er passeret, og at du ser halen af den.
Så til den misforståelse, der ødelægger læsningen af disse tal mest af alt. Load average i Linux er ikke «processorforbrug». I modsætning til andre Unix-systemer tæller Linux ikke kun processer med, som kører eller er klar til at køre, men også dem i tilstand D — uafbrydelig søvn. Altså venten på disken eller på et netværksfilsystem. Deraf serveren med load 12 og en næsten uvirksom processor: arbejdet skrider ikke frem, alle står i kø.
Processor eller disk
At skille de to tilfælde ad er det første, der er værd at gøre:
vmstat 1 5
iostat -x 1 3
I udskriften fra vmstat tæller tre kolonner. r er, hvor mange processer der står i kø til processoren, b hvor mange der er blokeret i venten på ind- og uddata, og wa den andel af tiden, processoren har stået uvirksom og ventet på disken. Et wa, der vedvarende ligger over 10–15 % ved beskedne us og sy, betyder, at serveren er begrænset af disken: at tilføje kerner nytter ikke, de eksisterende er allerede ledige.
Hvilke processer der venter, kan listes ved navn:
ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'
Et eksempel fra egen praksis. Med standardopsætningen skriver Suricata omkring tredive hændelsestyper og sætter ingen rotation op for dem — på en produktionsserver gav det 15 GB logfiler på to døgn. Belastningen viste sig da ikke som en travl processor, men netop som I/O wait: systemet skrev uafbrudt, og alt andet stod i kø bag ved. Løsningen er ikke et større abonnement, men en kortere liste over hændelsestyper og en opsat rotation.
Det modsatte tilfælde, rent processorbundet og betydeligt mindre indlysende. En webside kaldte apt som den bruger, PHP-FPM kører under. Root holder en binær cache i /var/cache/apt/pkgcache.bin — 70 MB på en vært med et dusin pakkearkiver — og lægger den i hukommelsen gratis. En almindelig bruger må ikke skrive i det katalog og genopbygger cachen ved hvert kald. Målt på én og samme maskin: 0,01 sekunder processortid som root mod 4,2 sekunder som bruger uden rettigheder. Samme kommando, en forskel på fire hundrede gange, ganget med hver sidevisning.
Konklusionen fra begge tilfælde er den samme: belastning skal måles, ikke gættes. At tage tid på hver mistænkt kommando for sig tager en halv time og peger som regel et andet sted hen, end mistanken begyndte.
Hukommelse: free viser ikke det, det ligner
free -h
Kolonnen used siger i sig selv meget lidt, og kolonnen free er direkte vildledende: Linux giver ubrugt hukommelse til sidecachen og tager den tilbage til programmerne ved første forespørgsel. Kolonnen, der skal læses, er available — hvor meget der kan optages uden at gå i swap. En stor buff/cache er ikke et problem, men tegnet på et system, der virker efter hensigten.
Ved swap er det ikke den aktuelle værdi, der tæller, men formen. Op og tilbage til nul: der var en kort spids. Op én gang og blevet der: spidsen har allerede været, sider er skubbet ud, og ingen henter dem tilbage — serveren ser rolig ud, selv om hukommelsen på et tidspunkt ikke slog til. Om der byttes lige nu, viser kolonnerne si og so i vmstat; værdier forskellige fra nul dér er den form for langsomhed, brugerne mærker tydeligst.
Hvis en proces simpelthen forsvandt under nattens dyk, står forklaringen som regel her:
journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"
En linje som Out of memory: Killed process 1234 (mysqld) afgør sagen bedre end noget diagram: databasen «faldt ikke om af sig selv», kernen stoppede den, fordi hukommelsen slap op.
Hvem der gør det
ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10
Ét forbehold: %CPU i ps er et gennemsnit over hele processens levetid, så en kort spids forsvinder på den liste. Til den skal der bruges top eller pidstat 1 5, som måler over et interval.
Hvornår belastning bliver et sikkerhedsspørgsmål
Jævne 100 % processor om natten, med en proces med et intetsigende navn og arbejdskatalog i /tmp eller /dev/shm, er det klassiske billede af en miner og ikke af et websted, der er vokset. En spids i indgående trafik sammen med øget skrivning til logfilerne er et igangværende adgangskodeangreb. En logmængde, der pludselig skyder i vejret, er som regel en storm af falske udslag fra et filter.
Sikkerhedsværktøjerne selv er en kategori for sig. På en af vores servere lå belastningen omkring tre helt uden besøgende, og øverst i ps efter akkumuleret processortid stod hverken webstedet eller databasen, men CrowdSec, fail2ban, Falco og Suricata. Det er hverken en fejl eller en grund til at slukke dem, men prisen for beskyttelsen er værd at kende i tal: på en lille VPS kan den mærkes.
Hvad observationen er til for
Alt det ovenstående besvarer spørgsmålet «hvad sker der nu». Morgenens spørgsmål — hvad skete der klokken tre i nat — dækkes ikke af disse kommandoer: om natten, der gik, findes der ingen data, hvis ingen har optaget dem. Og at stille Prometheus og Grafana op for en enkelt VPS er tvivlsomt, eftersom den observerende stak bliver tungere end den observerede server.
Det er nok med en række i en database hvert femte minut og én side, der tegner det seneste døgn ud fra den: load average, processorforbrug og I/O wait hver for sig, hukommelse og swap, læsning og skrivning på disken, partitionens fyldning, inoder, filbeskrivelser, forbindelser. På én tidsakse kan parrene læses med det blotte øje: højt wa med en rolig processor, swap der aldrig vendte tilbage til nul, beskrivelser tæt på grænsen — den kommende fejl too many open files bliver synlig timer, før den indtræffer. Hvordan det ser ud samlet, viser demosiden nedenfor.