Sanal makinesi "yavaş" diye şikâyet eden herkesin sunucusuna baktığımda karşıma çıkan ilk şey neredeyse hep aynı: disk denetleyicisi hâlâ IDE ya da SATA taklidinde bırakılmış. VirtIO sürücüleri ve disk performansı arasındaki ilişki burada devreye girer — çünkü sanallaştırmanın kendisi yavaş değildir; yavaş olan, gerçek bir donanımı bit bit taklit etmeye çalışan sanal denetleyicidir. Doğru denetleyiciye geçmek çoğu zaman tek satırlık bir değişiklikle disk verimini kat kat artırır.
Bu yazıda VirtIO'nun neden hızlı olduğunu, VirtIO Block ile VirtIO SCSI arasındaki farkı, cache modlarının veri güvenliği açısından ne anlama geldiğini, iothread ve discard gibi ayarların ne yaptığını ve Windows konuklarda sürücüyü kurulum sırasında nasıl yükleyeceğinizi anlatacağım. Sonda da ölçüm yaparken insanları yanıltan tuzakları toplayacağım; yanlış ölçülmüş bir performans testi, yanlış yapılandırmadan daha çok zaman kaybettirir.
Paravirtualizasyon: VirtIO Neden Hızlı#
Klasik sanal donanım taklidinde QEMU, gerçek bir Intel disk denetleyicisinin ya da bir e1000 ağ kartının davranışını yazılımla canlandırır. Konuk sürücü, sanki gerçek donanıma yazıyormuş gibi kayıtlara (register) yazar; QEMU her yazmayı yakalar, yorumlar ve karşılığını yapar. Bu yakalama işlemi (VM exit) pahalıdır — her biri CPU'da bağlam değişimi demektir ve saniyede binlerce kez tekrarlanır.
VirtIO farklı bir yol izler: gerçek bir donanımı taklit etmez, sanallaştırma için tasarlanmış bir arayüz sunar. Konuk, sanal bir makinede olduğunu bilir ve isteklerini paylaşımlı bellekteki halka tamponlara (virtqueue) yazar; hipervizör bu tamponları toplu hâlde işler. Böylece yüzlerce küçük yakalama yerine tek bir bildirim yeterli olur. Buna paravirtualizasyon denir ve VirtIO'nun hız farkının tamamı buradan gelir.
| Denetleyici | Tip | Tipik kullanım | Performans |
|---|---|---|---|
| IDE | Tam taklit | Çok eski konuklar, kurtarma | Çok düşük |
| SATA (AHCI) | Tam taklit | Sürücüsü olmayan konuklar | Düşük-orta |
| VirtIO Block | Paravirtual | Basit tek diskli makineler | Yüksek |
| VirtIO SCSI | Paravirtual | Önerilen varsayılan | Yüksek |
| VirtIO SCSI single | Paravirtual | Disk başına ayrı denetleyici | En yüksek |
Tablodaki son satır, Proxmox'un modern kurulumlarda varsayılan olarak önerdiği seçenektir ve iothread ile birlikte kullanıldığında her disk kendi denetleyicisine ve kendi G/Ç iş parçacığına sahip olur.
VirtIO Block mü VirtIO SCSI mi#
İkisi de paravirtual ve ikisi de hızlıdır; fark yetenek setindedir. VirtIO Block (virtio0, virtio1…) doğrudan bir blok cihaz sunar; basittir, az kod yolu kullanır ve tek diskli basit makinelerde son derece iyi çalışır. Ancak SCSI komut setini konuşmadığı için bazı yeteneklerden mahrumdur.
VirtIO SCSI ise bir SCSI denetleyicisi sunar ve diskler onun arkasına takılır. Bu, birkaç önemli kapı açar: discard/TRIM desteğiyle silinen alanın depolamaya geri bildirilmesi, disk sayısında pratik bir sınır olmaması, SSD emülasyonu bayrağı ve gerektiğinde fiziksel bir diskin doğrudan geçirilmesi. Bugün yeni bir makine kuruyorsanız cevap nettir: VirtIO SCSI single kullanın.
# Yeni makine oluştururken doğru denetleyici
qm create 220 --name db-01 --memory 8192 --cores 4 \
--scsihw virtio-scsi-single \
--scsi0 local-lvm:100,iothread=1,discard=on,ssd=1 \
--net0 virtio,bridge=vmbr0 --ostype l26
# Mevcut bir makinede denetleyiciyi değiştirme
qm set 220 --scsihw virtio-scsi-single
# Yapılandırmayı doğrula
qm config 220 | grep -E "scsihw|scsi0"
# scsihw: virtio-scsi-single
# scsi0: local-lvm:vm-220-disk-0,discard=on,iothread=1,size=100G,ssd=1
Buradaki üç disk seçeneğinin anlamı şudur: iothread=1 bu disk için ayrı bir G/Ç iş parçacığı açar ve yoğun yükte ana QEMU döngüsünün tıkanmasını önler; discard=on konuktaki fstrim işleminin depolamaya kadar ulaşmasını sağlar (ince tahsisli depolamada alan geri kazanımı için şart); ssd=1 ise konuğa diskin dönmeyen bir disk olduğunu söyler, böylece konuk zamanlayıcısı gereksiz sıralama optimizasyonu yapmaz.
discard ayarının neden önemli olduğunu ve alan geri kazanımının nasıl işlediğini thin provisioning nedir yazısında ayrıntılı ele alıyorum; ince tahsisli bir havuzda bu ayar kapalıysa silinen veriler depolamada yer kaplamaya devam eder.
Cache Modları ve Veri Güvenliği#
Disk performansı tartışmasının en yanıltıcı kısmı burasıdır, çünkü bazı cache modları testlerde muhteşem sonuçlar verir ama elektrik kesintisinde veri kaybettirir. Cache modu, konuğun yazma isteklerinin ana makine önbelleğinde nasıl ele alınacağını belirler.
| Mod | Ana makine önbelleği | Elektrik kesintisinde | Ne zaman kullanılır |
|---|---|---|---|
none | Atlanır (O_DIRECT) | Güvenli | Varsayılan tercih; canlı taşımaya uygun |
writeback | Kullanılır, yazma önbelleklenir | Riskli (konuk flush yapıyorsa kabul edilebilir) | Yazma yoğun, kesintiye dayanıklı iş yükleri |
writethrough | Okuma önbelleklenir, yazma hemen diske | Güvenli ama yavaş | Nadiren |
directsync | Önbellek yok, her yazma senkron | En güvenli, en yavaş | Kritik veri, yavaşlığa razıysanız |
unsafe | Flush komutları yok sayılır | Veri kaybı garantisi | Yalnızca geçici test makineleri |
Pratik tavsiye şudur: varsayılan olarak none kullanın. Depolama katmanınızda kendi güvenilir önbelleği olan bir denetleyici (BBU'lu RAID kartı) ya da ZFS gibi bir dosya sistemi varsa zaten iki kat önbellekleme yapmanın anlamı yoktur. writeback yalnızca ne yaptığınızı bilerek ve kesinti riskini kabul ederek seçilmelidir. unsafe ise adını hak eder: flush komutlarını tamamen yok sayar, bu yüzden yalnızca kaybı önemsenmeyen test makinelerinde kullanılır.
# Cache modunu ayarlama
qm set 220 --scsi0 local-lvm:vm-220-disk-0,cache=none,iothread=1,discard=on,ssd=1
# Bir kıyaslama yaparken cache modunun etkisini görmek için
# konuk içinde doğrudan G/Ç ile ölç (sayfa önbelleğini atla)
fio --name=yazma --filename=/tmp/test.bin --size=2G \
--rw=randwrite --bs=4k --iodepth=32 --numjobs=1 \
--direct=1 --ioengine=libaio --runtime=60 --time_based --group_reporting
rm -f /tmp/test.bin
--direct=1 parametresi burada kritiktir; olmadan konuğun kendi sayfa önbelleğini ölçersiniz ve gerçekte diskinizin ne yaptığı hakkında hiçbir şey öğrenmezsiniz.
Windows Konuklarda VirtIO Sürücü Kurulumu#
Linux çekirdeği VirtIO sürücülerini yerleşik olarak taşır; Windows taşımaz. Bu yüzden Windows kurulumunda VirtIO SCSI diskini seçtiğinizde kurulum sihirbazı "sürücü bulunamadı, disk yok" der ve çoğu kişi burada pes edip IDE'ye geri döner. Doğru yol, sürücüyü kurulum sırasında yüklemektir:
- Windows ISO'sunu birinci CD-ROM'a, VirtIO sürücü ISO'sunu ikinci CD-ROM'a bağlayın.
- Kurulumu başlatın; disk seçim ekranında "Sürücü Yükle" / "Load driver" bağlantısına tıklayın.
- VirtIO ISO'sunda
vioscsi\<sürüm>\amd64klasörünü seçin; disk artık görünecektir. - Aynı ekranda ağ için
NetKVM, bellek yönetimi içinBalloonsürücülerini de yükleyin. - Kurulum bittikten sonra ISO'daki
virtio-win-guest-toolspaketini çalıştırıp guest agent dahil tüm bileşenleri kurun.
Zaten IDE ile kurulmuş bir Windows makinesini VirtIO'ya geçirmek daha zahmetlidir, çünkü Windows önyükleme diskini tanımayan bir sürücüyle açılmaz ve mavi ekran verir. Güvenli yöntem şudur: makineye ikinci, küçük bir VirtIO SCSI diski ekleyip Windows'u bir kez açın — Windows sürücüyü kurar ve tanır. Sonra makineyi kapatıp asıl diski VirtIO SCSI'ye taşıyın ve geçici diski silin. Sürücü artık yüklü olduğu için sistem sorunsuz açılır.
Windows tarafında sürücü paketiyle birlikte gelen guest agent'ı da kurmayı unutmayın; tutarlı yedek ve düzgün kapatma buna bağlıdır. Ayrıntılar için QEMU Guest Agent kurulumu yazısına bakın.
Depolama Katmanının Payı#
Denetleyici doğru seçildiğinde performansı belirleyen sıradaki katman depolamadır ve buradaki seçimler denetleyiciden daha büyük fark yaratabilir. Aynı VirtIO SCSI ayarıyla, altındaki depolama tipine göre sonuçlar tamamen değişir.
| Depolama | Anlık görüntü | İnce tahsis | Tipik performans karakteri |
|---|---|---|---|
| LVM (kalın) | Hayır | Hayır | Öngörülebilir, düşük ek yük |
| LVM-thin | Evet | Evet | Çok iyi, alan verimli |
| ZFS | Evet | Evet | Güçlü özellikler, RAM ister |
| Directory (qcow2) | Evet | Evet | Esnek, ek yük biraz daha fazla |
| Ağ depolama (NFS/iSCSI) | Değişir | Değişir | Ağ gecikmesine bağımlı |
Disk formatının performansa etkisi ayrı bir konudur; qcow2 ile raw arasındaki gerçek fark ve hangi durumda hangisinin tercih edileceği için sanal disk formatları: qcow2, raw ve vmdk yazısına bakabilirsiniz.
Ana makinede darboğazın gerçekten diskte olup olmadığını anlamak için ölçüm yapın:
# Ana makinede disk kuyruğu ve bekleme süreleri
iostat -x 2 5
# %util 100'e yakın ve await yüksekse disk doymuş demektir
# Hangi süreç ne kadar G/Ç yapıyor
iotop -oPa
# Konuk içinden basit bir okuma testi (önbelleği atlayarak)
hdparm -t --direct /dev/sda
Disk doluluğunun performansa etkisini de unutmayın: ince tahsisli bir havuz doluluk sınırına yaklaştığında yazma performansı düşer ve en kötü durumda makineler donar. Doluluk takibi için disk kullanımı: df, du ve ncdu yazısındaki araçlar ana makinede de aynen geçerlidir.
Ölçüm Yaparken Düşülen Tuzaklar#
Performans tartışmalarının çoğu, hatalı ölçümler üzerine kurulduğu için sonuçsuz kalır. En sık yapılan hataları sıralayayım.
Önbelleği ölçmek. dd if=/dev/zero of=test bs=1M count=1000 komutu, oflag=direct olmadan çoğunlukla RAM hızını ölçer ve size 3 GB/s gibi güzel ama anlamsız bir sayı verir. Doğrudan G/Ç kullanmayan hiçbir ölçüme güvenmeyin.
Sıralı okuma ile rastgele yazmayı karıştırmak. Bir veritabanının derdi 4K rastgele yazma performansıdır; sıralı okuma testinin sonucu o iş yükü hakkında neredeyse hiçbir şey söylemez. Ölçtüğünüz desenin gerçek iş yükünüze benzemesi gerekir.
Tek seferlik ölçüm yapmak. İnce tahsisli depolamada ilk yazma, blok tahsisi gerektirdiği için ikinci yazmadan yavaştır. qcow2 üzerinde ilk yazma L2 tablosu güncellemesi de tetikler. En az bir ısıtma turu yapıp sonra ölçün.
Komşu yükü hesaba katmamak. Aynı fiziksel diski paylaşan başka makineler varken yaptığınız ölçüm, o anki komşu trafiğini de içerir. Ölçümü tekrarlayıp tutarlılığa bakın.
Konuk zamanlayıcısını unutmak. SSD üzerinde çalışan bir konukta mq-deadline yerine none zamanlayıcısı genellikle daha iyidir, çünkü sıralama işini alt katman zaten yapıyordur:
# Konuk içinde mevcut zamanlayıcıyı gör
cat /sys/block/sda/queue/scheduler
# [mq-deadline] kyber bfq none
# SSD tabanlı depolamada 'none' genelde daha uygun
echo none > /sys/block/sda/queue/scheduler
Bu değişikliği kalıcı yapmak için bir udev kuralı yazmanız ya da çekirdek parametresi eklemeniz gerekir; tek satırlık echo yeniden başlatmada kaybolur.
Sıkça Sorulan Sorular#
VirtIO SCSI ile VirtIO Block arasında hız farkı var mı#
Ham hız açısından fark çok küçüktür; ikisi de paravirtual arayüz kullandığı için IDE/SATA'ya göre kat kat hızlıdır. Aradaki gerçek fark yeteneklerdedir: VirtIO SCSI discard/TRIM destekler, çok sayıda diski tek denetleyici altında toplayabilir ve SSD emülasyonu sunar. Yeni kurulumlarda VirtIO SCSI single tercih etmenizi öneririm; kaybettiğiniz bir şey yok, kazandığınız esneklik var.
Cache modu olarak hangisini seçmeliyim#
Varsayılan tercihiniz none olmalı. Bu mod ana makinenin sayfa önbelleğini atlar, veri güvenliği açısından güvenlidir ve canlı taşımaya engel çıkarmaz. writeback daha hızlı görünür ama elektrik kesintisinde veri kaybı riski taşır; yalnızca kaybı göze alabileceğiniz iş yüklerinde ve UPS destekli sistemlerde düşünülmelidir. unsafe modunu üretimde asla kullanmayın.
IDE ile kurduğum Windows'u VirtIO'ya nasıl geçiririm#
Doğrudan değiştirirseniz Windows önyükleme sırasında mavi ekran verir, çünkü sürücü yüklü değildir. Güvenli yöntem şu: makineye küçük bir ikinci VirtIO SCSI diski ekleyin, Windows'u açın ve sürücüyü tanımasını sağlayın (gerekirse VirtIO ISO'sundan kurun). Sonra makineyi kapatıp asıl diski VirtIO SCSI'ye taşıyın ve geçici diski kaldırın. Bu sırayla sistem sorunsuz açılır.
iothread ayarı gerçekten fark yaratır mı#
Yoğun G/Ç yapan makinelerde evet. iothread=1 olmadan tüm disk işlemleri ana QEMU döngüsü üzerinden geçer; çok çekirdekli ve yoğun yazma yapan bir iş yükünde bu döngü darboğaz olur. Ayrı iş parçacığı, G/Ç'yi ana döngüden ayırarak gecikmeyi düşürür ve CPU'yu daha iyi kullanır. Hafif iş yüklerinde fark ölçülemeyecek kadar küçük olabilir ama zararı da yoktur.
Sanal makine diski neden fiziksel diskten yavaş#
Bir miktar ek yük her zaman vardır ama doğru yapılandırmada bu yüzde birkaç seviyesindedir. Belirgin bir yavaşlık görüyorsanız sırayla şunlara bakın: denetleyici hâlâ IDE/SATA mı, cache modu ne, iothread açık mı, ana makinedeki disk zaten doymuş mu (iostat -x) ve depolama ince tahsisliyse havuz doluluk sınırına yaklaşmış mı. Bu beş maddeden biri neredeyse her zaman sorunu açıklar.
discard ayarını açmak riskli mi#
Hayır, modern kurulumlarda güvenlidir ve ince tahsisli depolamada açık olması gerekir. discard=on konuktaki fstrim işleminin depolama katmanına ulaşmasını sağlar; böylece silinen dosyaların kapladığı alan gerçekten geri kazanılır. Kapalı bıraktığınızda havuz zamanla dolar ve silme işlemleri hiçbir alan kazandırmaz. Tek dikkat edilecek nokta, çok eski konuk çekirdeklerinde TRIM desteğinin sorunlu olabilmesidir.
Kapanış#
Sanal makine disk performansının büyük kısmı, birkaç doğru seçimle belirlenir. Aklınızda kalması gereken dört alışkanlık şunlar: yeni makineleri VirtIO SCSI single ile kurun, cache modunu none bırakın ve writeback'i ancak bilinçli olarak seçin, yoğun G/Ç yapan disklerde iothread ve discard ayarlarını açın, ve performans ölçerken mutlaka doğrudan G/Ç kullanıp gerçek iş yükünüze benzeyen bir desen ölçün.
Bu ayarlarla uğraşmadan hızlı NVMe depolamalı bir sunucuya geçmek isterseniz VDS ve sanal sunucu paketlerimiz VirtIO ile hazır yapılandırılmış gelir. Daha yüksek ve öngörülebilir G/Ç gerektiren iş yükleri için dedicated sunucu, esnek ölçeklenme için bulut sunucu seçeneklerine bakabilir, ayar ve izleme tarafını devretmek isterseniz sunucu yönetimi hizmetimizden yararlanabilirsiniz.