Spørsmålet lyder nesten alltid likt: i natt brukte nettstedet tjue sekunder på å svare, og til morgenen hadde alt ordnet seg av seg selv. Det er ingenting igjen å se på — top svarer for det inneværende sekundet, mens spørsmålet gjelder klokken tre om natten. Nedenfor: hva belastningstallene faktisk betyr, hvilke av dem som må leses parvis, og hvorfor en enkeltmåling villeder oftere enn den hjelper.

Load average: tre tall og en utbredt misforståelse

uptime
cat /proc/loadavg
nproc

De tre tallene er gjennomsnitt over ett, fem og femten minutter. De skal ikke sammenlignes med null, men med antallet kjerner som nproc oppgir. Verdien 8 på en maskin med åtte kjerner er full, men sunn belastning: det er nøyaktig så mye arbeid som serveren klarer å utføre. Verdien 2 på en VPS med én kjerne er en kø dobbelt så lang som kapasiteten, og hver forespørsel venter på tur.

Forholdet mellom de tre tallene viser retningen. Ettminuttsverdien klart over femtenminuttsverdien betyr at belastningen stiger akkurat nå. Motsatt betyr at toppen er over og at du ser halen av den.

Så til misforståelsen som ødelegger lesningen av disse tallene mest av alt. Load average i Linux er ikke «prosessorbruk». I motsetning til andre Unix-systemer teller Linux ikke bare med prosesser som kjører eller er klare til å kjøre, men også dem som er i tilstand D — uavbrytelig søvn. Det vil si venting på disken eller på et nettverksfilsystem. Derav serveren med load 12 og en nesten uvirksom prosessor: arbeidet går ikke framover, alle står i kø.

Prosessor eller disk

Å skille disse to tilfellene er det første som er verdt å gjøre:

vmstat 1 5
iostat -x 1 3

I utdataene fra vmstat er det tre kolonner som teller. r er hvor mange prosesser som står i kø til prosessoren, b hvor mange som er blokkert i påvente av inn- og utdata, og wa andelen av tiden prosessoren har stått uvirksom og ventet på disken. En wa som holder seg over 10–15 % ved moderate us og sy betyr at serveren begrenses av disken: å legge til kjerner hjelper ikke, de som finnes er allerede ledige.

Hvilke prosesser som venter, kan listes opp ved navn:

ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'

Et eksempel fra egen praksis. Med standardoppsettet skriver Suricata rundt tretti hendelsestyper og setter ikke opp noen rotasjon for dem — på en produksjonsserver ga det 15 GB logger på to døgn. Belastningen viste seg da ikke som opptatt prosessor, men nettopp som I/O wait: systemet skrev uavbrutt, og alt annet sto i kø bak. Botemiddelet er ikke et større abonnement, men en kortere liste over hendelsestyper og en oppsatt rotasjon.

Det motsatte tilfellet, rent prosessorbundet og langt mindre åpenbart. En nettside kalte apt som brukeren PHP-FPM kjører under. Root holder en binær hurtigbuffer i /var/cache/apt/pkgcache.bin — 70 MB på en vert med et dusin pakkebrønner — og legger den i minnet gratis. En vanlig bruker får ikke skrive i den katalogen og bygger bufferen på nytt ved hvert kall. Målt på én og samme maskin: 0,01 sekunder prosessortid som root mot 4,2 sekunder som bruker uten rettigheter. Samme kommando, en forskjell på fire hundre ganger, multiplisert med hver sidevisning.

Konklusjonen fra begge tilfellene er den samme: belastning skal måles, ikke gjettes. Å ta tiden på hver mistenkt kommando for seg tar en halvtime og peker som regel et annet sted enn der mistanken startet.

Minne: free viser ikke det det ser ut som

free -h

Kolonnen used sier i seg selv svært lite, og kolonnen free er direkte villedende: Linux gir ubrukt minne til sidebufferen og tar det tilbake til programmene ved første forespørsel. Kolonnen som skal leses er available — hvor mye som kan tas i bruk uten å gå til swap. En stor buff/cache er ikke et problem, men tegnet på et system som virker som det skal.

For swap er det ikke den aktuelle verdien som teller, men formen. Opp og tilbake til null: det var en kort topp. Opp én gang og blitt der: toppen har allerede vært, sider er skjøvet ut, og ingen henter dem tilbake — serveren ser rolig ut selv om minnet på et tidspunkt ikke strakk til. Om utveksling skjer akkurat nå, vises i kolonnene si og so i vmstat; verdier ulik null der er den formen for treghet brukerne merker tydeligst.

Hvis en prosess rett og slett forsvant under nattens fall, 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) avgjør saken bedre enn noe diagram: databasen «falt ikke om av seg selv», kjernen stoppet den fordi minnet tok slutt.

Hvem som gjør det

ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

Ett forbehold: %CPU i ps er et gjennomsnitt over hele prosessens levetid, så en kort topp forsvinner i den listen. Til den trengs top eller pidstat 1 5, som måler over et intervall.

Når belastning blir et sikkerhetsspørsmål

Jevne 100 % prosessor om natten, med en prosess med intetsigende navn og arbeidskatalog i /tmp eller /dev/shm, er det klassiske bildet av en utvinner og ikke av et nettsted som har vokst. En topp i innkommende trafikk sammen med økt skriving til loggene er et pågående passordangrep. Et loggvolum som plutselig skyter i været, er som regel en storm av falske utslag fra et filter.

Sikkerhetsverktøyene selv er en egen kategori. På en av våre servere lå belastningen rundt tre helt uten besøkende, og øverst i ps etter oppsamlet prosessortid sto verken nettstedet eller databasen, men CrowdSec, fail2ban, Falco og Suricata. Det er verken en feil eller en grunn til å slå dem av, men prisen for beskyttelsen er verdt å kjenne i tall: på en liten VPS merkes den.

Hva observasjonen er til for

Alt det ovenstående svarer på spørsmålet «hva skjer nå». Morgenens spørsmål — hva skjedde klokken tre i natt — dekkes ikke av disse kommandoene: om natten som gikk finnes det ingen data hvis ingen har registrert dem. Og å sette opp Prometheus og Grafana for én enkelt VPS er tvilsomt, siden stakken som observerer blir tyngre enn serveren som observeres.

Det holder med en rad i en database hvert femte minutt og én side som tegner det siste døgnet ut fra den: load average, prosessorbruk og I/O wait hver for seg, minne og swap, lesing og skriving mot disk, fyllingsgrad på partisjonen, inoder, filbeskrivelser, tilkoblinger. På én tidsakse kan parene leses med det blotte øye: høy wa med rolig prosessor, swap som aldri kom tilbake til null, beskrivelser nær grensen — den kommende feilen too many open files blir synlig timer før den inntreffer. Hvordan dette ser ut satt sammen, viser demosiden nedenfor.