Kysymys kuuluu lähes aina samalla tavalla: yöllä sivusto vastasi kahdessakymmenessä sekunnissa, ja aamuun mennessä kaikki oli korjaantunut itsestään. Katsottavaa ei ole enää — top vastaa kuluvasta sekunnista, kun kysymys koskee kello kolmea yöllä. Seuraavassa käydään läpi, mitä kuormaluvut oikeasti tarkoittavat, mitkä niistä on luettava pareittain ja miksi yksittäinen mittaus johtaa harhaan useammin kuin auttaa.

Load average: kolme lukua ja yksi yleinen väärinkäsitys

uptime
cat /proc/loadavg
nproc

Kolme lukua ovat keskiarvoja yhden, viiden ja viidentoista minuutin ajalta. Niitä ei verrata nollaan vaan ytimien määrään, jonka nproc kertoo. Arvo 8 kahdeksanytimisessä koneessa on täysi mutta terve kuorma: työtä on täsmälleen sen verran kuin palvelin ehtii tehdä. Arvo 2 yksiytimisellä VPS:llä on jono, joka on kaksi kertaa kapasiteettia pidempi, ja jokainen pyyntö odottaa vuoroaan.

Lukujen suhde toisiinsa kertoo suunnan. Yhden minuutin arvo selvästi viidentoista minuutin arvon yläpuolella tarkoittaa, että kuorma nousee juuri nyt. Päinvastainen tarkoittaa, että huippu on ohi ja näkyvissä on vain sen häntä.

Nyt se väärinkäsitys, joka pilaa näiden lukujen lukemisen useimmin. Load average ei Linuxissa ole ”suorittimen käyttöaste”. Toisin kuin muut Unix-järjestelmät, Linux laskee siihen mukaan paitsi suoritettavat tai suoritusvalmiit prosessit myös ne, jotka ovat tilassa D — keskeytymättömässä unessa. Toisin sanoen odottavat levyä tai verkkotiedostojärjestelmää. Siitä johtuu palvelin, jonka kuorma on 12 ja suoritin lähes toimeton: työ ei etene, kaikki jonottavat.

Suoritin vai levy

Näiden kahden tapauksen erottaminen on ensimmäinen tekemisen arvoinen asia:

vmstat 1 5
iostat -x 1 3

Komennon vmstat tulosteessa merkitystä on kolmella sarakkeella. r kertoo, montako prosessia jonottaa suorittimelle, b montako on estettynä odottamassa siirräntää, ja wa sen osuuden ajasta, jonka suoritin on ollut toimettomana levyä odottaen. Jatkuvasti yli 10–15 %:n wa vaatimattomilla us- ja sy-arvoilla tarkoittaa, että palvelinta rajoittaa levy: ytimien lisääminen ei auta, olemassa olevat ovat jo vapaina.

Odottavat prosessit voi luetella nimeltä:

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

Esimerkki omasta käytännöstä. Oletusasetuksilla Suricata kirjoittaa noin kolmeakymmentä tapahtumatyyppiä eikä määrittele niille mitään kiertoa — tuotantopalvelimella siitä kertyi 15 Gt lokia kahdessa vuorokaudessa. Kuorma ei näkynyt kiireisenä suorittimena vaan nimenomaan I/O waitina: järjestelmä kirjoitti taukoamatta ja kaikki muu jonotti sen takana. Ratkaisu ei ole isompi paketti vaan lyhyempi lista tapahtumatyyppejä ja määritelty kierto.

Päinvastainen tapaus, puhtaasti suoritinsidonnainen ja huomattavasti vähemmän ilmeinen. Verkkosivu kutsui apt-komentoa sillä käyttäjällä, jolla PHP-FPM ajetaan. Root pitää binääristä välimuistia tiedostossa /var/cache/apt/pkgcache.bin — tusinan pakettivaraston isännässä 70 Mt — ja liittää sen muistiin ilmaiseksi. Tavallinen käyttäjä ei saa kirjoittaa tuohon hakemistoon ja rakentaa välimuistin uudelleen joka kutsulla. Mitattuna yhdellä ja samalla koneella: 0,01 sekuntia suoritinaikaa rootina ja 4,2 sekuntia oikeudettomana käyttäjänä. Sama komento, neljäsataakertainen ero, kerrottuna jokaisella sivunlatauksella.

Molempien tapausten johtopäätös on sama: kuorma on mitattava, ei arvattava. Jokaisen epäillyn komennon ajan ottaminen erikseen vie puoli tuntia ja osoittaa yleensä muualle kuin sinne, mistä epäily lähti.

Muisti: free ei näytä sitä, miltä se näyttää

free -h

Sarake used yksinään kertoo hyvin vähän, ja sarake free johtaa suorastaan harhaan: Linux antaa käyttämättömän muistin sivuvälimuistille ja ottaa sen takaisin sovelluksille ensimmäisestä pyynnöstä. Luettava sarake on available — kuinka paljon voi varata joutumatta swapiin. Suuri buff/cache ei ole ongelma vaan merkki järjestelmästä, joka toimii kuten pitääkin.

Swapissa ei merkitse nykyinen arvo vaan muoto. Nousi ja palasi nollaan: kyseessä oli lyhyt huippu. Nousi kerran ja jäi siihen: huippu on jo ollut, sivuja on siirretty pois eikä kukaan tuo niitä takaisin — palvelin näyttää rauhalliselta, vaikka muisti jossain vaiheessa loppui. Käykö vaihto juuri nyt, näkyy vmstat-komennon sarakkeista si ja so; nollasta poikkeavat arvot ovat se hitauden muoto, jonka käyttäjät huomaavat selvimmin.

Jos jokin prosessi yksinkertaisesti katosi yöllisen notkahduksen aikana, selitys löytyy yleensä täältä:

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

Rivi Out of memory: Killed process 1234 (mysqld) ratkaisee asian paremmin kuin mikään kuvaaja: tietokanta ei ”kaatunut itsestään”, ydin pysäytti sen, koska muisti loppui.

Kuka sitä tekee

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

Yksi varaus: ps-komennon %CPU on keskiarvo prosessin koko eliniältä, joten lyhyt piikki hukkuu tuohon listaan. Sitä varten tarvitaan top tai pidstat 1 5, jotka mittaavat aikavälillä.

Milloin kuormasta tulee tietoturvakysymys

Tasainen 100 %:n suoritinkuorma yöllä, kun prosessin nimi on merkityksetön ja työhakemisto on /tmp tai /dev/shm, on klassinen kuva louhijasta eikä kasvaneesta sivustosta. Saapuvan liikenteen piikki yhdessä lisääntyneen lokiin kirjoittamisen kanssa on käynnissä oleva salasanahyökkäys. Äkillisesti kasvava lokimäärä on yleensä jonkin suodattimen väärien hälytysten myrsky.

Suojaustyökalut itse ovat oma luokkansa. Yhdellä palvelimistamme kuorma pysyi kolmen tienoilla ilman ainuttakaan kävijää, ja ps-listan kärjessä kertyneen suoritinajan mukaan eivät olleet sivusto eikä tietokanta vaan CrowdSec, fail2ban, Falco ja Suricata. Se ei ole vika eikä syy sammuttaa niitä, mutta suojauksen hinta kannattaa tuntea numeroina: pienellä VPS:llä se tuntuu.

Mihin seurantaa tarvitaan

Kaikki edellä sanottu vastaa kysymykseen ”mitä nyt tapahtuu”. Aamun kysymystä — mitä tapahtui kello kolme yöllä — nämä komennot eivät kata: menneestä yöstä ei ole tietoja, jos kukaan ei ole niitä tallentanut. Ja Prometheuksen ja Grafanan pystyttäminen yhtä VPS:ää varten on kyseenalaista, koska seuraava pino painaa enemmän kuin seurattava palvelin.

Riittää rivi tietokantaan viiden minuutin välein ja yksi sivu, joka piirtää siitä viimeisen vuorokauden: load average, suorittimen käyttöaste ja I/O wait erikseen, muisti ja swap, levyn luku ja kirjoitus, osion täyttöaste, i-solmut, tiedostokahvat, yhteydet. Yhdellä aika-akselilla parit lukee paljain silmin: korkea wa rauhallisella suorittimella, swap joka ei koskaan palannut nollaan, kahvat lähellä rajaa — tuleva virhe too many open files näkyy tunteja ennen kuin se tapahtuu. Miltä tämä kaikki näyttää koottuna, esittää alla oleva demosivu.