Disk I/O Performansını Ölçme: iostat ve fio Kullanım Kılavuzu

Sunucuda bir şeyler ters gittiğinde, genellikle ilk suçlanan CPU veya RAM olur. Ama deneyimli bir sysadmin olarak söylüyorum: çoğu zaman asıl katil disk I/O’dur. Yavaş veritabanı sorguları, uygulama takılmaları, yüksek load average ama düşük CPU kullanımı… Bunların büyük bir kısmının arkasında disk darboğazı yatar. Bu yazıda, disk I/O performansını doğru ölçmek için kullandığım iki temel aracı, iostat ve fio‘yu, gerçek dünya senaryolarıyla birlikte detaylı şekilde ele alacağım.

Neden Disk I/O İzleme Bu Kadar Kritik?

Bir web sunucusunda sayfa yüklemeleri yavaşlamaya başladı. top komutuna baktınız, CPU %15’te. RAM kullanımı normal. Ama sistem hala yavaş. İşte bu noktada iowait değerine bakmanız gerekiyor. Eğer iowait yüksekse, CPU’nuz aslında disk işlemlerinin tamamlanmasını bekliyor demektir. Bu durum, modern SSD’lerin yaygınlaşmasıyla birlikte daha az görülse de, özellikle yoğun veritabanı iş yüklerinde, eski HDD’lerde ve sanallaştırılmış ortamlarda hala çok sık karşılaşılan bir sorun.

Disk I/O darboğazlarını anlamak için iki farklı yaklaşıma ihtiyacınız var:

  • Anlık izleme: Sistemin şu an nasıl davrandığını görmek için (iostat)
  • Benchmark testleri: Diskin gerçek kapasitesini ölçmek için (fio)

iostat ile Anlık Disk Performansı İzleme

iostat, sysstat paketinin bir parçasıdır. Çoğu dağıtımda varsayılan olarak gelir, ama gelmiyorsa:

# Debian/Ubuntu
apt-get install sysstat

# RHEL/CentOS/Rocky Linux
yum install sysstat
# veya
dnf install sysstat

Temel iostat Kullanımı

En basit haliyle iostat şöyle çalışır:

# Temel çıktı
iostat

# 2 saniyede bir, 10 kez güncelle
iostat -x 2 10

# Belirli bir disk için izleme
iostat -x sda 2

Ama asıl işe yarayan komut -x parametresiyle genişletilmiş istatistikleri görmektir:

iostat -xz 2

Bu komutun çıktısını ilk gördüğünüzde biraz karmaşık gelebilir. Sütunları tek tek açıklayayım:

  • r/s: Saniyede tamamlanan okuma istekleri
  • w/s: Saniyede tamamlanan yazma istekleri
  • rkB/s: Saniyede okunan kilobyte miktarı
  • wkB/s: Saniyede yazılan kilobyte miktarı
  • rrqm/s: Saniyede birleştirilen okuma istekleri (kernel optimizasyonu)
  • wrqm/s: Saniyede birleştirilen yazma istekleri
  • r_await: Okuma isteklerinin ortalama bekleme süresi (milisaniye)
  • w_await: Yazma isteklerinin ortalama bekleme süresi (milisaniye)
  • aqu-sz: Ortalama I/O kuyruk boyutu
  • %util: Diskin meşgul olduğu sürenin yüzdesi

Gerçek Dünya Senaryosu 1: Yüksek iowait Analizi

Gece 2’de bir alarm geldi, uygulama sunucusu yavaşlamış. SSH’la bağlandınızda şunu yapın:

# Önce genel duruma bakın
iostat -xz 1 5

# Eş zamanlı olarak başka bir terminalde
vmstat 1 5

vmstat çıktısında wa (wait) sütununa bakın. Bu değer sürekli 20’nin üzerindeyse, ciddi bir I/O probleminiz var demektir.

iostat çıktısında şunlara dikkat edin:

  • %util değeri sürekli %90’ın üzerindeyse disk doymuş demektir
  • r_await veya w_await değerleri HDD için 20ms’nin, SSD için 1ms’nin üzerindeyse sorun var
  • aqu-sz değeri 1’in üzerinde ve artıyorsa disk istekleri kuyrukta bekliyor
# Hangi process'lerin I/O yaptığını görmek için
iotop -o -d 2

# iotop yoksa
pidstat -d 2

iostat Çıktısını Daha Okunabilir Hale Getirmek

Ham çıktı bazen gözü yoruyor. Şu alias’ları .bashrc‘ye ekleyebilirsiniz:

# Sadece aktif diskleri göster, 2 sn aralıkla
alias iostat-watch='iostat -xz --human 2'

# JSON formatında çıktı (log analizi için)
iostat -xz -o JSON 2 5 > /var/log/iostat_$(date +%Y%m%d_%H%M%S).json

--human parametresi MB/s, GB/s gibi okunabilir birimler kullanır, bu özellikle raporlama yaparken çok işe yarar.

iostat ile Tarihsel Veri Toplama

Anlık izleme güzel ama gerçek sorunları yakalamak için tarihsel veri şart. sysstat paketinin sar aracıyla entegre çalışan bir cron job kurabilirsiniz:

# /etc/cron.d/sysstat dosyasını kontrol edin
# Genellikle varsayılan olarak 10 dakikada bir veri toplar

# Toplanan verileri görüntülemek için
sar -d -p 2

# Dünün disk istatistiklerini görmek için
sar -d -p -f /var/log/sa/sa$(date -d yesterday +%d)

fio ile Disk Benchmark Testleri

iostat size mevcut durumu gösterirken, fio (Flexible I/O Tester) diskinizin gerçekte ne kadar performans verebileceğini ölçer. Bu ayrımı kafaya yerleştirmek önemli. Bir sunucu aldınız ve “Bu SSD gerçekten söylediği performansı veriyor mu?” sorusunu yanıtlamak istiyorsanız, fio tam size göre.

fio Kurulumu

# Debian/Ubuntu
apt-get install fio

# RHEL/CentOS/Rocky Linux
yum install fio

# Kaynak koddan derleme (en güncel sürüm için)
git clone https://github.com/axboe/fio.git
cd fio && ./configure && make && make install

fio’nun Temel Parametreleri

fio’yu anlamak, parametrelerini anlamaktan geçer:

  • –name: Test adı, çıktıda görünür
  • –filename: Test edilecek disk veya dosya yolu
  • –rw: I/O tipi (read, write, randread, randwrite, randrw, readwrite)
  • –bs: Block size (4k, 8k, 128k, 1m gibi)
  • –size: Test dosyasının toplam boyutu
  • –numjobs: Paralel iş parçacığı sayısı
  • –runtime: Testin çalışma süresi (saniye)
  • –ioengine: I/O motoru (libaio, sync, psync, io_uring)
  • –iodepth: Aynı anda kuyruktaki I/O derinliği (async için önemli)
  • –direct: Direct I/O kullanımı (1 = OS cache bypass)
  • –group_reporting: Çoklu job sonuçlarını tek raporda göster

Gerçek Dünya Senaryosu 2: Yeni Sunucu Disk Testi

Yeni bir NVMe SSD takılmış sunucu geldi. Üretim ortamına almadan önce şu testleri yapıyorum:

# 1. Sıralı okuma testi (büyük dosya transferleri için önemli)
fio --name=seq-read 
    --filename=/dev/sdb 
    --rw=read 
    --bs=1m 
    --size=10g 
    --numjobs=1 
    --runtime=60 
    --ioengine=libaio 
    --iodepth=32 
    --direct=1 
    --group_reporting

# 2. Sıralı yazma testi
fio --name=seq-write 
    --filename=/dev/sdb 
    --rw=write 
    --bs=1m 
    --size=10g 
    --numjobs=1 
    --runtime=60 
    --ioengine=libaio 
    --iodepth=32 
    --direct=1 
    --group_reporting

Dikkat: --filename=/dev/sdb ile doğrudan diske yazıyorsanız, bu disk üzerinde veri olmamalı! Test mevcut verilerin üzerine yazar.

Gerçek Dünya Senaryosu 3: Veritabanı İş Yükü Simülasyonu

Bir MySQL veya PostgreSQL sunucusu için disk seçimi yapıyorsunuz. Veritabanları genellikle küçük, rastgele I/O operasyonları yapar. Bu yüzden 4K random read/write testleri kritik:

# Veritabanı iş yükü simülasyonu
# Önce test için bir dosya oluşturun (production diskte)
fio --name=db-simulation 
    --filename=/var/lib/mysql/fio_test 
    --rw=randrw 
    --rwmixread=70 
    --bs=4k 
    --size=4g 
    --numjobs=4 
    --runtime=120 
    --ioengine=libaio 
    --iodepth=64 
    --direct=1 
    --group_reporting 
    --lat_percentiles=1 
    --percentile_list=50:90:95:99:99.9

Bu testte --rwmixread=70 parametresi %70 okuma, %30 yazma karışımını simüle eder. Çoğu veritabanı iş yükü bu oranlara yakındır.

Çıktıda şunlara bakın:

  • IOPS: Saniyedeki I/O operasyonu sayısı. Veritabanı için kritik.
  • BW (Bandwidth): Saniyedeki veri aktarım hızı
  • lat (99.9th): En kötü %0.1’lik gecikme. Bu değer yüksekse kullanıcılar ara ara takılma yaşar
  • clat percentiles: Gecikme dağılımı

Gerçek Dünya Senaryosu 4: NVMe vs SATA SSD Karşılaştırması

İki farklı disk teknolojisi arasında karar vermeniz gerekiyor. fio ile sistematik bir karşılaştırma yapabilirsiniz:

# Test sonuçlarını dosyaya kaydet
fio --name=nvme-4k-randread 
    --filename=/mnt/nvme/fio_test 
    --rw=randread 
    --bs=4k 
    --size=8g 
    --numjobs=1 
    --runtime=60 
    --ioengine=libaio 
    --iodepth=128 
    --direct=1 
    --output-format=json 
    --output=/tmp/nvme_4k_randread.json

# Aynı testi SATA SSD için
fio --name=sata-4k-randread 
    --filename=/mnt/sata/fio_test 
    --rw=randread 
    --bs=4k 
    --size=8g 
    --numjobs=1 
    --runtime=60 
    --ioengine=libaio 
    --iodepth=128 
    --direct=1 
    --output-format=json 
    --output=/tmp/sata_4k_randread.json

JSON çıktısı oluşturduğunuzda, bu verileri Python veya jq ile kolayca işleyebilirsiniz:

# IOPS değerini JSON çıktısından çek
jq '.jobs[0].read.iops' /tmp/nvme_4k_randread.json
jq '.jobs[0].read.lat_ns.percentile."99.000000"' /tmp/nvme_4k_randread.json

fio Job Dosyaları ile Tekrarlanabilir Testler

Komut satırı parametreleri uzadıkça karmaşıklaşır. Benim tercihim, testleri .fio uzantılı job dosyalarında tanımlamak:

# /etc/fio/production_disk_test.fio
cat << 'EOF' > /etc/fio/production_disk_test.fio
[global]
ioengine=libaio
direct=1
runtime=60
time_based
group_reporting
lat_percentiles=1

[seq-read-1m]
rw=read
bs=1m
iodepth=32
numjobs=1
filename=/dev/sdb
size=10g

[rand-read-4k]
rw=randread
bs=4k
iodepth=64
numjobs=4
filename=/dev/sdb
size=10g

[rand-write-4k]
rw=randwrite
bs=4k
iodepth=64
numjobs=4
filename=/dev/sdb
size=10g
EOF

# Çalıştır
fio /etc/fio/production_disk_test.fio

Bu yaklaşımın güzelliği şu: Aynı job dosyasını farklı sunucularda çalıştırarak tutarlı karşılaştırmalar yapabiliyorsunuz. Git’e koyun, ekip arkadaşlarınızla paylaşın.

iostat ve fio’yu Birlikte Kullanmak

Asıl güç bu ikisini birlikte kullanmaktan geliyor. Şöyle bir senaryo düşünün: Production’da yavaşlama var.

# Terminal 1: iostat ile anlık izleme başlat
iostat -xz 1 > /tmp/iostat_live.log &
IOSTAT_PID=$!

# Terminal 2: Sistemi simüle eden fio testi
fio --name=workload-sim 
    --filename=/data/fio_test 
    --rw=randrw 
    --rwmixread=70 
    --bs=4k 
    --size=2g 
    --numjobs=8 
    --runtime=60 
    --ioengine=libaio 
    --iodepth=32 
    --direct=1

# fio bittikten sonra iostat'ı durdur
kill $IOSTAT_PID

# Sonuçları analiz et
grep -E "sdb|sda" /tmp/iostat_live.log | tail -20

Böylece hem diskin maksimum kapasitesini hem de gerçek koşullardaki davranışını görmüş olursunuz.

Performans Sorunlarını Yorumlamak

Sayıları topladınız, şimdi ne yapacaksınız? Birkaç pratik kural:

HDD için normal değerler:

  • Sıralı okuma/yazma: 100-200 MB/s
  • Random 4K IOPS: 100-200
  • r/w_await: 5-20ms normal, 20ms üzeri sorunlu

SATA SSD için normal değerler:

  • Sıralı okuma: 500-550 MB/s
  • Sıralı yazma: 450-520 MB/s
  • Random 4K okuma IOPS: 80.000-100.000
  • r/w_await: 0.1-0.5ms normal

NVMe SSD için normal değerler:

  • Sıralı okuma: 3.000-7.000 MB/s
  • Random 4K okuma IOPS: 500.000-1.000.000+
  • r/w_await: 0.01-0.1ms normal

Eğer iostat çıktısında %util sürekli %80’in üzerindeyse, şu çözümleri değerlendirin:

  • I/O scheduler’ı değiştirin (mq-deadline veya none NVMe için)
  • Read-ahead değerini iş yüküne göre optimize edin
  • Dosya sistemi mount seçeneklerini gözden geçirin (noatime, nodiratime)
  • RAID yapılandırmasını veya LVM cache katmanını düşünün
# I/O scheduler'ı kontrol etme ve değiştirme
cat /sys/block/sda/queue/scheduler
echo "mq-deadline" > /sys/block/sda/queue/scheduler

# Read-ahead değerini değiştirme (512 = 256KB)
blockdev --setra 512 /dev/sda

Sonuç

Disk I/O performans analizi, sysadmin işinin en çok sabır isteyen ama aynı zamanda en tatmin edici yanlarından biri. iostat ile mevcut durumu anlık takip ederken, fio ile diskinizin gerçek sınırlarını keşfediyorsunuz. Bu iki aracı birlikte kullandığınızda, hem “şu an ne oluyor?” sorusuna hem de “bu disk bu iş yükünü taşıyabilir mi?” sorusuna net cevaplar verebiliyorsunuz.

Benim önerim: Yeni bir sunucu kurduğunuzda fio testlerini mutlaka yapın ve sonuçları kaydedin. Altı ay sonra performans düşmeye başladığında, elimizde kıyaslama noktamız olsun. Production sorunlarında ise iostat, iotop ve pidstat üçlüsünü kombine kullanmayı alışkanlık haline getirin. Çoğu zaman sorunun kaynağı, bu araçların birkaç dakikalık çıktısında kendiliğinden ortaya çıkıyor.

Son olarak şunu da söylemeliyim: En iyi disk I/O optimizasyonu, gereksiz I/O’yu ortadan kaldırmaktır. Uygulama katmanında doğru caching, veritabanında doğru index yapısı ve dosya sistemi seçimi, diskin fiziksel kapasitesini artırmaktan çok daha etkili olabilir. Ama bunları tartışmak için ayrı bir yazı gerekir.

Yorum yapın