Soru neredeyse her zaman aynıdır: gece site yanıt vermek için yirmi saniye harcıyordu, sabaha kadar da her şey kendiliğinden düzeldi. Bakılacak bir şey kalmamıştır — top içinde bulunulan saniyeyi yanıtlar, oysa sorulan gece üçtür. Aşağıda yük sayılarının gerçekte ne anlama geldiğini, hangilerinin çiftler hâlinde okunması gerektiğini ve tek seferlik bir ölçümün neden yardım etmekten çok yanılttığını bulacaksınız.

Load average: üç sayı ve yaygın bir yanlış anlama

uptime
cat /proc/loadavg
nproc

Üç sayı, bir, beş ve on beş dakikalık ortalamalardır. Sıfırla değil, nproc komutunun bildirdiği çekirdek sayısıyla karşılaştırılırlar. Sekiz çekirdekli bir makinede 8 değeri tam ama sağlıklı yüktür: sunucunun yetişebileceği kadar iş vardır. Tek çekirdekli bir VPS’te 2 değeri, kapasitenin iki katı uzunlukta bir kuyruktur ve her istek sırasını bekler.

Üç sayının birbirine oranı yönü verir. Bir dakikalık değerin on beş dakikalığın belirgin biçimde üzerinde olması, yükün tam şu anda arttığı anlamına gelir. Tersi ise tepe noktasının geçtiğini ve yalnızca kuyruğunun görüldüğünü gösterir.

Şimdi bu sayıların en sık yanlış okunmasına yol açan yanılgıya gelelim. Linux’ta load average «işlemci kullanımı» değildir. Diğer Unix sistemlerinden farklı olarak Linux buna yalnızca çalışan ya da çalışmaya hazır süreçleri değil, D durumundakileri — kesintiye uğratılamaz uykudakileri — de katar. Yani diski veya bir ağ dosya sistemini bekleyenleri. Yükü 12 olan ama işlemcisi neredeyse boş duran sunucu buradan gelir: iş ilerlemiyordur, herkes sıradadır.

İşlemci mi, disk mi

Bu iki durumu ayırmak yapılmaya değer ilk iştir:

vmstat 1 5
iostat -x 1 3

vmstat çıktısında üç sütun önemlidir. r, işlemci için sırada bekleyen süreç sayısıdır; b, giriş-çıkış beklerken engellenmiş olanların sayısı; wa ise işlemcinin boş durup diski beklediği zaman oranıdır. us ve sy mütevazıyken sürekli %10–15 üzerinde seyreden bir wa, sunucunun diske takıldığını gösterir: çekirdek eklemek işe yaramaz, mevcut olanlar zaten boştur.

Hangi süreçlerin beklediği adlarıyla listelenebilir:

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

Kendi uygulamamızdan bir örnek. Suricata, varsayılan yapılandırmayla otuz kadar olay türü yazar ve bunlar için hiçbir döndürme ayarlamaz — çalışan bir sunucuda bu, iki günde 15 GB günlük demek oldu. Yük burada meşgul bir işlemci olarak değil, tam olarak I/O wait olarak görünüyordu: sistem aralıksız yazıyor, geri kalan her şey onun arkasında sırada bekliyordu. Çözüm daha büyük bir paket değil, daha kısa bir olay türü listesi ve kurulmuş bir döndürmedir.

Tersi durum, tamamen işlemciye bağlı ve çok daha az göze çarpan. Bir web sayfası, PHP-FPM’in çalıştığı kullanıcıyla apt komutunu çağırıyordu. Root, /var/cache/apt/pkgcache.bin dosyasında ikili bir önbellek tutar — bir düzine depo bulunan bir makinede bu 70 MB’dir — ve onu belleğe bedavaya eşler. Sıradan bir kullanıcı o dizine yazamaz ve her çağrıda önbelleği baştan kurar. Aynı makinede ölçüldü: root olarak 0,01 saniye işlemci zamanı, yetkisiz kullanıcı olarak 4,2 saniye. Aynı komut, dört yüz kat fark ve bu farkın her sayfa açılışıyla çarpılması.

Her iki durumdan çıkan sonuç aynıdır: yük ölçülür, tahmin edilmez. Şüpheli her komutun süresini ayrı ayrı almak yarım saat sürer ve genellikle şüphenin başladığı yerden bambaşka bir yeri gösterir.

Bellek: free göründüğü şeyi göstermez

free -h

used sütunu tek başına çok az şey söyler, free sütunu ise doğrudan yanıltır: Linux kullanılmayan belleği sayfa önbelleğine verir ve ilk istekte uygulamalara geri döndürür. Okunması gereken sütun available’dır — swap’a düşmeden ne kadarının kullanılabileceği. Büyük bir buff/cache sorun değil, sistemin olması gerektiği gibi çalıştığının işaretidir.

Swap’ta önemli olan anlık değer değil, biçimdir. Yükselip sıfıra dönmüşse kısa bir tepe olmuştur. Bir kez yükselip orada kalmışsa tepe çoktan yaşanmıştır, sayfalar dışarı atılmıştır ve kimse onları geri getirmez; sunucu sakin görünür, oysa bir noktada belleği yetmemiştir. Takasın şu anda sürüp sürmediğini vmstat içindeki si ve so sütunları gösterir; oradaki sıfırdan farklı değerler, kullanıcıların en çok hissettiği yavaşlama biçimidir.

Gece çöküşü sırasında bir süreç kaybolduysa açıklama genellikle buradadır:

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

Out of memory: Killed process 1234 (mysqld) biçimindeki bir satır meseleyi her grafikten daha iyi kapatır: veritabanı «kendi kendine çökmedi», bellek bittiği için çekirdek onu durdurdu.

Buna kim yol açıyor

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

Bir çekince: ps içindeki %CPU, sürecin tüm yaşamı boyunca alınmış bir ortalamadır, bu yüzden kısa bir sıçrama o listede kaybolur. Onun için aralıkla ölçen top ya da pidstat 1 5 gerekir.

Yük ne zaman bir güvenlik sorusuna dönüşür

Gece boyunca düz bir %100 işlemci, adı hiçbir şey ifade etmeyen ve çalışma dizini /tmp ya da /dev/shm olan bir süreçle birlikte, büyümüş bir sitenin değil, klasik bir madencinin görüntüsüdür. Gelen trafikteki bir sıçramanın günlüklere yazmanın artmasıyla birlikte görülmesi, süregelen bir parola saldırısıdır. Aniden fırlayan günlük hacmi ise genellikle bir filtrenin yanlış alarm fırtınasıdır.

Koruma araçlarının kendisi ayrı bir kategoridir. Sunucularımızdan birinde hiç ziyaretçi yokken yük üç civarında duruyordu ve biriken işlemci zamanına göre ps listesinin başında ne site ne de veritabanı vardı; CrowdSec, fail2ban, Falco ve Suricata duruyordu. Bu bir arıza değildir ve onları kapatmak için bir gerekçe de değildir, ama korumanın bedelini sayılarla bilmekte yarar vardır: küçük bir VPS’te hissedilir.

İzlemek ne işe yarar

Yukarıdakilerin hepsi «şu anda ne oluyor» sorusunu yanıtlar. Sabahki soruyu — gece üçte ne oldu — bu komutlar kapsamaz: geçen geceye ait veri, onu kimse kaydetmediyse yoktur. Tek bir VPS için Prometheus ve Grafana kurmak ise tartışmalıdır, çünkü izleyen yığın izlenen sunucudan ağır çıkar.

Beş dakikada bir veritabanına yazılan bir satır ve buradan son yirmi dört saati çizen tek bir sayfa yeter: load average, işlemci kullanımı ve ayrı olarak I/O wait, bellek ve swap, disk okuma ve yazma, bölümün dolulukları, inode’lar, dosya tanıtıcıları, bağlantılar. Tek bir zaman ekseninde çiftler çıplak gözle okunur: sakin bir işlemciyle birlikte yüksek wa, sıfıra hiç dönmemiş bir swap, sınıra yaklaşan tanıtıcılar — yaklaşan too many open files hatası gerçekleşmesinden saatler önce görünür hâle gelir. Bütün bunların bir arada nasıl göründüğünü aşağıdaki tanıtım sayfası gösteriyor.