Load average lezen op multi-core machines: de drie misverstanden en de alert die wél werkt
Load 8 is rustig op een 16-core en een ramp op een 2-core. Load telt ook processen die op een schijf wachten, niet alleen CPU. En de 1-minuut-waarde is bijna altijd ruis. Wat de drie getallen echt betekenen, hoe je ze normaliseert per core, hoe je CPU-druk van I/O-druk onderscheidt met /proc/pressure, en welke drempel je in een alert zet.
Inhoud
- Misverstand 1: "load is CPU-gebruik"
- Misverstand 2: "load boven 1 is slecht"
- Misverstand 3: "de 1-minuut-waarde is de actuele"
- De betere bron: /proc/pressure (PSI)
- De alert die wél werkt
- Wat doe je als de alert afgaat?
- Valkuilen
- Wat je hiermee nog niet hebt
- Zo doet monsys het
- FAQ
load average: 6.12, 5.87, 4.90 — en dan? De meeste dashboards tonen die drie getallen prominent en de meeste beheerders hebben er een gevoel bij dat ongeveer klopt. "Ongeveer" is het probleem: de load average is geen percentage, telt op Linux méér dan alleen CPU, en betekent op een 32-core machine iets totaal anders dan op een VPS met 2 vCPU's. Dit artikel maakt er een getal van dat je kunt interpreteren, en een alert die niet elke nacht om 03:00 afgaat.
Misverstand 1: "load is CPU-gebruik"
De load average is het gemiddelde aantal processen dat runnable is (wil CPU, heeft het al of wacht erop) plus, op Linux, processen in uninterruptible sleep (state D: wachten op een schijf, NFS, een swap-in). Dat tweede stuk is een Linux-eigenaardigheid uit 1993 en de bron van de meeste verwarring.
cat /proc/loadavg
# 6.12 5.87 4.90 3/1187 481223
# │ │ │ │ │ └─ laatste PID
# │ │ │ │ └─ totaal aantal threads
# │ │ │ └─ runnable op dit moment
# └────┴────┴─ 1, 5, 15 minuten (exponentieel gedempt gemiddelde)
# Wie draagt bij? Runnable (R) en uninterruptible (D) threads, nu:
ps -eo state,pid,comm | awk '$1=="R"||$1=="D"' | sort | uniq -c | sort -rn | head
Zie je veel D-processen, dan is je load een I/O-verhaal, geen CPU-verhaal — en meer cores lossen niets op.
Misverstand 2: "load boven 1 is slecht"
Load is absoluut, niet relatief. Op een machine met N cores is load N het punt waarop elke core precies één taak heeft. Deel dus altijd door het aantal cores:
nproc # 8
awk -v c="$(nproc)" '{printf "load per core: %.2f %.2f %.2f\n", $1/c, $2/c, $3/c}' /proc/loadavg
# load per core: 0.77 0.73 0.61
Vuistregels voor het 15-minuten-getal per core:
| Load per core (15 min) | Betekenis |
|---|---|
| < 0,7 | Ruimte over |
| 0,7 – 1,0 | Volledig benut, geen wachtrij — prima voor een batch-server, krap voor een webserver |
| 1,0 – 2,0 | Structurele wachtrij: elke taak wacht gemiddeld op één andere |
| > 2,0 | Overbelast, of I/O-blokkade (controleer D-state) |
Let op containers en VM's: nproc in een container geeft het aantal cores van de host, maar je cgroup mag er misschien maar twee gebruiken. cat /sys/fs/cgroup/cpu.max toont de quota (200000 100000 = 2 cores).
Misverstand 3: "de 1-minuut-waarde is de actuele"
De drie getallen zijn exponentieel gedempte gemiddelden. De 1-minuut-waarde reageert het snelst, maar bevat dus ook elke apt update, elke logrotate en elke cron die drie seconden alle cores pakte. Voor beslissingen kijk je naar de 15-minuten-waarde; voor "is er nú iets aan de hand" kijk je niet naar de load maar naar de wachtrij zelf:
vmstat 1 5
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st gu
# 9 2 0 812344 102212 4211200 0 0 120 3400 2100 5100 71 12 9 8 0 0
r = runnable threads (vergelijk met nproc), b = geblokkeerd op I/O, wa = percentage tijd dat CPU's wachten op I/O, st = steal (je hoster geeft je minder CPU dan beloofd — op een VPS het eerste waar je naar kijkt).
De betere bron: /proc/pressure (PSI)
Sinds kernel 4.20 houdt Linux per resource bij hoeveel procent van de tijd taken wachten — CPU, geheugen en I/O apart. Dat is precies de vraag die load probeert te beantwoorden, maar dan zonder de vermenging.
cat /proc/pressure/cpu
# some avg10=4.21 avg60=3.87 avg300=2.10 total=81234567
cat /proc/pressure/io
# some avg10=18.40 avg60=12.31 avg300=6.02 total=...
# full avg10=9.11 avg60=5.20 avg300=2.40 total=...
cat /proc/pressure/memory
some = percentage van de tijd dat minstens één taak wachtte; full = alle taken wachtten (de machine stond stil op die resource). Een io full avg60 van 9 % betekent: 9 % van de laatste minuut deed niemand iets omdat de schijf niet bijkwam. Dát is de alert die je wilt — niet "load > 4".
PSI staat aan op Ubuntu 24.04 en Debian 12. Ontbreekt /proc/pressure, dan zit psi=1 niet in de kernel-cmdline.
De alert die wél werkt
Drie regels, in volgorde van betrouwbaarheid:
cpu some avg300 > 25— een kwart van de laatste 5 minuten wachtte er iets op CPU. Structureel, geen piek.io full avg300 > 5— de machine stond 5 % van de tijd volledig stil op I/O. Schijf, NFS of swap.load15 / nproc > 2— de klassieke vangnet-regel, alleen als PSI niet beschikbaar is.
sudo tee /usr/local/sbin/pressure-check.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
NTFY="https://ntfy.example.be/servers"; HOST=$(hostname -s); MSG=()
psi() { awk -v k="$1" -v w="$2" '$1==k { for(i=2;i<=NF;i++) if ($i ~ "^"w"=") { sub(w"=","",$i); print $i } }' "/proc/pressure/$3"; }
if [ -r /proc/pressure/cpu ]; then
c=$(psi some avg300 cpu); i=$(psi full avg300 io); m=$(psi full avg300 memory)
awk -v v="$c" 'BEGIN{exit !(v>25)}' && MSG+=("cpu pressure some/5m = ${c}%")
awk -v v="$i" 'BEGIN{exit !(v>5)}' && MSG+=("io pressure full/5m = ${i}%")
awk -v v="$m" 'BEGIN{exit !(v>2)}' && MSG+=("memory pressure full/5m = ${m}% (swap/OOM nabij)")
else
l=$(awk '{print $3}' /proc/loadavg); c=$(nproc)
awk -v l="$l" -v c="$c" 'BEGIN{exit !(l/c>2)}' && MSG+=("load15/core = $(awk -v l="$l" -v c="$c" 'BEGIN{printf "%.2f", l/c}')")
fi
# Steal: de hoster geeft je CPU niet. Kolom opzoeken op naam: nieuwere procps voegt "gu" (guest) toe na "st".
st=$(vmstat 1 2 | awk 'NR==2{for(i=1;i<=NF;i++) if($i=="st") c=i} END{print $c}')
[ "${st:-0}" -gt 10 ] && MSG+=("cpu steal ${st}% — hoster overcommit")
[ ${#MSG[@]} -gt 0 ] && printf '%s\n' "${MSG[@]}" | curl -s -H "Title: pressure@$HOST" -H "Priority: high" --data-binary @- "$NTFY" >/dev/null
EOF
sudo chmod 0755 /usr/local/sbin/pressure-check.sh
echo '*/5 * * * * root /usr/local/sbin/pressure-check.sh' | sudo tee /etc/cron.d/pressure-check
Wat doe je als de alert afgaat?
| Symptoom | Eerste commando | Typische oorzaak |
|---|---|---|
CPU-pressure hoog, r > nproc | top -o %CPU, pidstat 1 | Een runaway proces, een cron op het verkeerde uur, te weinig workers-limiet |
I/O-pressure hoog, veel D | iostat -xz 1, iotop -o | Backup, database-vacuum, logrotate met compressie, volle schijf, kapotte disk |
| Memory-pressure hoog | free -m, vmstat kolom si/so | Swappen; een geheugenlek dat nog nét niet OOM is |
| Steal hoog | niets lokaal | Je hoster. Ticket of migreren. |
Valkuilen
- Hyperthreading.
nproctelt logische cores. Twee threads op één fysieke core leveren geen 2× doorvoer; boven load ≈ 0,7 × fysieke cores merk je dat al.lscpu | grep -E 'Thread|Core'. - Containers.
/proc/loadavgin een container is de load van de hele host. Kijk naarcpu.statencpu.pressurein de cgroup van de container (/sys/fs/cgroup/<pad>/cpu.pressure). - NFS-hangs. Een niet-bereikbare NFS-server zet elk proces dat het pad aanraakt in
D-state. Load stijgt naar honderden terwijl de CPU idle is.io fullin PSI ziet het meteen; de load-alert zegt alleen "iets". - Alerteren op de 1-minuut-waarde. Elke
logrotatemet gzip levert een piek. Gebruik 5 of 15 minuten, of PSIavg300. - Vaste drempels op wisselende hardware. "load > 4" betekent op je 2-core dev-VM iets anders dan op de 48-core database. Normaliseer per core of gebruik PSI, dat al een percentage is.
Wat je hiermee nog niet hebt
- Historie. "Sinds wanneer staat de I/O-pressure op 8 %?" vraagt een tijdreeks;
sar -qgeeft load, maar geen PSI. - Normaal per uur. Op dinsdagnacht is load 6 normaal (backup); op dinsdagmiddag niet. Een vaste drempel kent dat verschil niet.
- De koppeling met wat het veroorzaakt. Pressure hoog om 03:00 en de backup-job die om 02:55 begon: twee logs.
Zo doet monsys het
De monsys-agent meet elke 15 seconden load, r/b uit vmstat, steal en de drie PSI-waarden, en de hub bouwt per host een uur-van-dag baseline: een anomaly_load_avg-regel vuurt op afwijking van wat deze host op dit uur normaal doet, niet op een absoluut getal. De alert toont de top-processen en de I/O-statistieken van hetzelfde moment, zodat de tabel hierboven al is ingevuld voor je inlogt.
FAQ
Wat is een goede load average?
Per core (load gedeeld door nproc) onder 0,7 op het 15-minuten-getal: dan is er ruimte. Tussen 0,7 en 1 is de machine vol maar zonder wachtrij. Boven 1 wachten taken structureel — of er is een I/O-probleem, wat je controleert met vmstat (kolom b, wa) of /proc/pressure/io.
Waarom is mijn load hoog terwijl de CPU idle is?
Omdat Linux processen in uninterruptible sleep (D-state, wachtend op schijf, NFS of swap) meetelt. Kijk naar ps -eo state,comm | grep ^D en /proc/pressure/io. Meer CPU helpt hier niet; snellere storage of een fix voor het hangende mount wel.
Is PSI beter dan load average?
Ja, voor alerting: het scheidt CPU, geheugen en I/O, het is een percentage (geen normalisatie nodig) en het meet wachttijd in plaats van aantal taken. Load average blijft nuttig als één snel getal, maar bouw je alerts op /proc/pressure.
Geschreven door het monsys-team — sysadmins die dit dagelijks doen.
Zelf gedaan? Laat monsys het bijhouden.
Alles uit deze how-to draait in monsys als doorlopende check, met historie, alerts en audit-bewijs. 5 servers gratis, EU-gehost in België, geïnstalleerd in 60 seconden.