De vraag luidt bijna altijd hetzelfde: vannacht deed de site er twintig seconden over om te antwoorden, en tegen de ochtend was alles vanzelf weer in orde. Er valt niets meer te bekijken — top antwoordt over de huidige seconde, terwijl de vraag over drie uur ’s nachts gaat. Hieronder: wat de belastingscijfers werkelijk betekenen, welke ervan in paren gelezen moeten worden, en waarom een losse meting vaker misleidt dan helpt.

Load average: drie getallen en één veelgemaakte denkfout

uptime
cat /proc/loadavg
nproc

De drie getallen zijn gemiddelden over één, vijf en vijftien minuten. Ze worden niet met nul vergeleken, maar met het aantal kernen dat nproc meldt. Een waarde van 8 op een machine met acht kernen is volle maar gezonde belasting: er ligt precies zoveel werk als de server aankan. Een waarde van 2 op een VPS met één kern is een wachtrij die twee keer zo lang is als de capaciteit, en elk verzoek wacht op zijn beurt.

De verhouding tussen de drie getallen geeft de richting aan. Het cijfer over één minuut duidelijk boven dat over vijftien minuten betekent dat de belasting nu aan het oplopen is. Andersom is de piek voorbij en ziet u alleen nog de staart ervan.

Dan de denkfout waar deze cijfers het vaakst op stuklopen. Load average is onder Linux geen «processorgebruik». Anders dan andere Unix-systemen telt Linux er niet alleen processen in mee die draaien of gereed staan, maar ook die in toestand D verkeren: ononderbreekbare slaap. Dat wil zeggen: wachten op de schijf of op een netwerkbestandssysteem. Vandaar de server met een load van 12 en een vrijwel stilstaande processor: er wordt niet gewerkt, er wordt gewacht.

Processor of schijf

Die twee gevallen scheiden is het eerste wat de moeite waard is:

vmstat 1 5
iostat -x 1 3

In de uitvoer van vmstat tellen drie kolommen. r is hoeveel processen in de rij staan voor de processor, b hoeveel er geblokkeerd zijn in afwachting van invoer/uitvoer, en wa het aandeel van de tijd dat de processor stil op de schijf heeft staan wachten. Een wa die duurzaam boven de 10–15 % ligt bij bescheiden us en sy betekent dat de server op de schijf vastloopt: kernen bijzetten heeft geen zin, de aanwezige zijn toch al vrij.

Welke processen staan te wachten, laat zich bij naam opsommen:

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

Een voorbeeld uit de eigen praktijk. Met de standaardconfiguratie schrijft Suricata een dertigtal soorten gebeurtenissen weg en regelt daar geen rotatie voor — op een productieserver leverde dat 15 GB aan logbestanden in twee dagen op. De belasting uitte zich daarbij niet als een bezette processor maar juist als I/O wait: het systeem schreef onophoudelijk en al het overige stond erachter in de rij. Het middel is geen groter abonnement, maar een kortere lijst gebeurtenissen en een ingestelde rotatie.

Het omgekeerde geval, puur processorgebonden en veel minder voor de hand liggend. Een webpagina riep apt aan onder de gebruiker waaronder PHP-FPM draait. Root houdt een binaire cache aan in /var/cache/apt/pkgcache.bin — 70 MB op een host met een dozijn repository’s — en koppelt die gratis in het geheugen. Een gewone gebruiker mag niet in die map schrijven en bouwt de cache bij elke aanroep opnieuw op. Gemeten op een en dezelfde machine: 0,01 seconde processortijd als root tegenover 4,2 seconden als gebruiker zonder rechten. Hetzelfde commando, een verschil van vierhonderd keer, vermenigvuldigd met elke paginaweergave.

De conclusie uit beide gevallen is dezelfde: belasting moet gemeten worden, niet geraden. Elk verdacht commando afzonderlijk klokken kost een half uur en wijst doorgaans ergens anders heen dan waar het vermoeden begon.

Geheugen: free laat niet zien wat het lijkt

free -h

De kolom used zegt op zichzelf bijzonder weinig, en de kolom free is ronduit misleidend: Linux geeft ongebruikt geheugen aan de paginacache en neemt het op eerste verzoek terug voor toepassingen. De kolom om te lezen is available — hoeveel er bezet kan worden zonder naar swap te gaan. Een grote buff/cache is geen probleem maar het teken van een systeem dat werkt zoals bedoeld.

Bij swap telt niet de huidige waarde maar de vorm. Omhoog en terug naar nul: er was een korte piek. Eén keer omhoog en daar gebleven: de piek is al geweest, pagina’s zijn verdrongen en niemand haalt ze terug — de server oogt rustig terwijl het geheugen op enig moment tekortschoot. Of er op dit moment wordt gewisseld, laten de kolommen si en so in vmstat zien; waarden ongelijk aan nul zijn daar de vorm van traagheid die gebruikers het sterkst merken.

Is er tijdens de nachtelijke terugval simpelweg een proces verdwenen, dan staat de verklaring meestal hier:

journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"

Een regel als Out of memory: Killed process 1234 (mysqld) beslist de zaak beter dan welke grafiek ook: de database is niet «vanzelf omgevallen», de kernel heeft haar gestopt omdat het geheugen op was.

Wie het veroorzaakt

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

Eén kanttekening: de %CPU in ps is een gemiddelde over de hele levensduur van het proces, dus een korte uitschieter gaat in die lijst verloren. Daarvoor zijn top of pidstat 1 5 nodig, die over een interval meten.

Wanneer belasting een beveiligingsvraag wordt

Een vlakke 100 % processor in de nacht, met een proces met een nietszeggende naam en een werkmap in /tmp of /dev/shm, is het klassieke beeld van een miner en niet dat van een gegroeide site. Een piek in binnenkomend verkeer samen met meer schrijfacties naar de logbestanden is een lopende wachtwoordaanval. Een logvolume dat plotseling omhoogschiet is doorgaans een storm van valse meldingen van een filter.

De beveiligingsgereedschappen zelf vormen een categorie apart. Op een van onze servers bleef de load rond de drie hangen zonder ook maar één bezoeker, en boven aan ps op opgebouwde processortijd stonden niet de site en niet de database, maar CrowdSec, fail2ban, Falco en Suricata. Dat is geen storing en geen reden om ze uit te zetten, maar de prijs van bescherming is het waard om in cijfers te kennen: op een kleine VPS is die merkbaar.

Waartoe dat waarnemen dient

Al het bovenstaande beantwoordt de vraag «wat gebeurt er nu». De ochtendvraag — wat is er om drie uur ’s nachts gebeurd — dekken deze commando’s niet: over de afgelopen nacht bestaan geen gegevens als niemand ze heeft vastgelegd. En Prometheus met Grafana optuigen voor één VPS is twijfelachtig, omdat de waarnemende stack zwaarder uitvalt dan de waargenomen server.

Eén regel in een database per vijf minuten en één pagina die daaruit de laatste 24 uur tekent, volstaan: load average, processorgebruik en I/O wait afzonderlijk, geheugen en swap, lezen en schrijven van de schijf, vulling van de partitie, inodes, bestandsdescriptors, verbindingen. Op één tijdas laten de paren zich met het blote oog lezen: hoge wa bij een rustige processor, swap die nooit naar nul terugkeerde, descriptors die de limiet naderen — de aanstaande fout too many open files wordt uren van tevoren zichtbaar. Hoe dat er samengesteld uitziet, toont de demopagina hieronder.