Server monitoringbeginner6 min lezen

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
  1. Misverstand 1: "load is CPU-gebruik"
  2. Misverstand 2: "load boven 1 is slecht"
  3. Misverstand 3: "de 1-minuut-waarde is de actuele"
  4. De betere bron: /proc/pressure (PSI)
  5. De alert die wél werkt
  6. Wat doe je als de alert afgaat?
  7. Valkuilen
  8. Wat je hiermee nog niet hebt
  9. Zo doet monsys het
  10. 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,7Ruimte over
0,7 – 1,0Volledig benut, geen wachtrij — prima voor een batch-server, krap voor een webserver
1,0 – 2,0Structurele wachtrij: elke taak wacht gemiddeld op één andere
> 2,0Overbelast, 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:

  1. cpu some avg300 > 25 — een kwart van de laatste 5 minuten wachtte er iets op CPU. Structureel, geen piek.
  2. io full avg300 > 5 — de machine stond 5 % van de tijd volledig stil op I/O. Schijf, NFS of swap.
  3. 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?

SymptoomEerste commandoTypische oorzaak
CPU-pressure hoog, r > nproctop -o %CPU, pidstat 1Een runaway proces, een cron op het verkeerde uur, te weinig workers-limiet
I/O-pressure hoog, veel Diostat -xz 1, iotop -oBackup, database-vacuum, logrotate met compressie, volle schijf, kapotte disk
Memory-pressure hoogfree -m, vmstat kolom si/soSwappen; een geheugenlek dat nog nét niet OOM is
Steal hoogniets lokaalJe hoster. Ticket of migreren.

Valkuilen

  • Hyperthreading. nproc telt 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/loadavg in een container is de load van de hele host. Kijk naar cpu.stat en cpu.pressure in 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 full in PSI ziet het meteen; de load-alert zegt alleen "iets".
  • Alerteren op de 1-minuut-waarde. Elke logrotate met gzip levert een piek. Gebruik 5 of 15 minuten, of PSI avg300.
  • 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 -q geeft 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.