手当たり次第に書くんだ

飽きっぽいのは本能

VM ストレージ I/O 設計 – virtio / cache / qcow2 / backend を確認する

VM の storage I/O は、仮想 disk format だけでは決まりません。guest filesystem、virtio device、QEMU block layer、host filesystem、logical volume、network、storage backend を通り、各層の queue と cache が latency と durability に影響します。

この記事では、guest から backend までを同じ時間窓で測定し、virtio-blk / virtio-scsi、raw / qcow2、cache mode、IOThread、discard、passthrough を、性能、データ保護、運用制約の 3 つで判断します。

storage I/O の経路を分ける

主な要素確認するもの
guestapplication、filesystem、block layerrequest size、queue、latency、fsync
virtual devicevirtio-blk、virtio-scsiqueue 数、driver、device feature
QEMUblock driver、cache、AIO、IOThreadprocess / thread、block counter、error
hostpage cache、filesystem、LVM、ZFSawait、queue、reclaim、thin pool
backendNVMe、RAID、Ceph、SAN、NASvolume latency、controller、network、rebuild

guest の disk latency が高くても、原因が guest にあるとは限りません。逆に backend の平均 latency が低くても、QEMU queue、snapshot chain、host cache、同期 write の待ち時間が guest の p99 に現れる場合があります。

症状と測定時間を固定する

調査では、遅い I/O の種類と発生時間を先に決めます。read / write、sequential / random、sync / async、block size、queue depth が違えば、同じ storage でも結果は変わります。

  • どの application operation が遅いか
  • read、write、flush、discard のどれか
  • 平均 latency と p95 / p99 latency はいくつか
  • IOPS、throughput、queue depth を同時に記録しているか
  • snapshot、backup、migration、rebuild と重なっていないか
  • 正常時と同じ workload 条件で比較できるか

counter は累積値を含むため、1 回だけ取得して判断しません。guest、libvirt、host、backend を同じ間隔で 2 回以上取得し、差分と workload の完了量を対応付けます。

guest 側で latency と queue を確認する

lsblk -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS,ROTA,DISC-MAX,DISC-GRAN
iostat -xz 1
vmstat 1
cat /proc/pressure/io
mount
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
所見候補次の確認
await と queue が増えるdevice または下位層の待ちhost と backend の同時 latency
utilization が高いdevice が busy完了 IOPS と latency が SLO 内か
I/O PSI が増えるtask の I/O stallどの process と cgroup が待つか
write だけ遅いflush、cache、replicationsync write と backend commit
discard 時だけ遅いunmap の伝搬と backend 処理online discard と fstrim の違い

%util が高いことだけで saturation と断定しません。並列処理できる device や storage array では、queue、latency、throughput、error を一緒に見ます。

libvirt から disk と counter を対応付ける

最初に domain の target device と source path を確認し、counter を対象 disk へ対応付けます。domblkstatdomstats で QEMU が公開する block 統計を取得し、XML で cache、I/O backend、discard、IOThread を確認します。

virsh domblklist vm01 --details
virsh domblkinfo vm01 vda
virsh domblkstat vm01 vda --human
virsh domstats vm01 --block --iothread
virsh dumpxml vm01
virsh dumpxml vm01 --inactive
qemu-img info --backing-chain /var/lib/libvirt/images/vm01.qcow2

qemu-img info の path は domblklist で確認します。active image を扱う操作は、read-only の情報取得と image を変更する操作を区別し、snapshot、commit、rebase、check などは maintenance 手順に分けます。

host と backend の同時負荷を確認する

iostat -xz 1
pidstat -d -p 12345 1
cat /proc/pressure/io
lsblk -o NAME,TYPE,SIZE,MODEL,ROTA,SCHED,DISC-MAX,DISC-GRAN
dmsetup status
lvs -o lv_name,vg_name,lv_size,data_percent,metadata_percent

QEMU の process ID は対象 VM と照合した値を使います。host device の latency が低いまま QEMU thread の待ちが増える場合と、同じ backend を使う複数 VM が同時に遅くなる場合では、優先して調べる層が異なります。

発生範囲優先する調査
1 application だけfsync、lock、database log、filesystem
1 VM の 1 diskvirtual device、image、IOThread、snapshot chain
1 VM の全 diskQEMU、host CPU / memory、共通 controller
同じ host の複数 VMhost device、thin pool、page cache、backup
複数 host の同じ volume 群storage network、array、Ceph、SAN / NAS

virtio-blk と virtio-scsi を用途で選ぶ

方式特徴確認すること
virtio-blkblock device を直接提示する単純な構成disk 数、queue、hotplug、guest driver
virtio-scsiSCSI controller 配下へ複数 device を接続するcontroller、SCSI feature、queue、hotplug

virtio device は paravirtualized device であり、一般的な VM では標準的な選択です。ただし、virtio-blk と virtio-scsi のどちらが速いかを形式名だけで決めません。guest kernel、queue 数、IOThread、block size、backend の並列性をそろえて測定します。

raw と qcow2 の差を image chain まで見る

形式得られるもの注意点
raw単純な block address と読みやすい経路sparse file、filesystem、thin volume の層は別に存在する
qcow2backing file、snapshot、thin allocation などmetadata、allocation、fragmentation、chain depth

raw file でも host filesystem や thin provisioning を使えば、allocation と snapshot の層は残ります。qcow2 でも workload と cache によって必要性能を満たせます。format だけでなく source type、backing chain、cluster allocation、snapshot 数、backend を記録します。

  • backing chain が意図せず深くなっていないか
  • internal snapshot と external snapshot の運用を混同していないか
  • backup 後の temporary overlay が残っていないか
  • virtual size と host の実使用量を分けているか
  • thin pool の data と metadata に余力があるか
  • image の変換や compact を active VM に対して実行していないか

cache mode は durability 契約として決める

cache mode は benchmark の速さだけでなく、guest の flush がどこまで伝わり、host や backend の障害でどの write を失う可能性があるかを決めます。guest filesystem、QEMU、host cache、storage controller の各層が flush と write ordering を守る必要があります。

mode経路の特徴検証すること
nonehost page cache を避ける構成で使われるdirect I/O の要件と backend の alignment
directsyncdirect I/O と同期 write を組み合わせるlatency と durability の要件
writethroughwrite 完了前の永続化を重視するbackend までの flush と性能
writebackcache を利用して完了を早く返せるguest flush、power loss protection、障害試験

storage に battery-backed cache や power loss protection があるか、network storage が write を何段階で acknowledge するかも確認します。mode 名だけでデータ保護を保証せず、guest の fsync、QEMU の flush、backend commit を一つの経路として検証します。

AIO と IOThread の役割を分ける

libvirt の disk driver では、環境に応じて threadsnativeio_uring などの I/O backend を選択できます。IOThread は disk I/O 処理を QEMU main loop から分けるための thread であり、AIO backend の名前とは別の設計要素です。

<iothreads>2</iothreads>
<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2' cache='none' io='io_uring' discard='unmap' iothread='1'/>
  <source file='/var/lib/libvirt/images/vm01.qcow2'/>
  <target dev='vda' bus='virtio'/>
  <iotune>
    <total_iops_sec>5000</total_iops_sec>
  </iotune>
</disk>

この XML は要素の関係を示す例です。io_uring、IOThread assignment、queue、iotune の対応可否は libvirt、QEMU、disk bus、source type によって異なります。現在の version と生成された QEMU command line を確認し、未対応の組み合わせを前提にしません。

I/O limit は noisy neighbor を抑える一方で、上限自体が latency の原因になります。iotune を設定している場合は、backend saturation と rate limit のどちらで待っているかを分けます。

discard は guest から backend まで追う

discard は guest で不要になった block を下位層へ伝える仕組みです。libvirt の discard='unmap' は要求を下位へ渡す指定ですが、guest filesystem、virtual device、image format、host filesystem、thin pool、storage backend の全層が対応する必要があります。

方式利点注意点
online discard解放時に随時伝えるworkload 中の latency と backend 負荷
定期 fstrim実行時間を制御しやすい一度に大きな unmap が発生する可能性
discard 無効実行時の変動を避けやすいthin allocation を回収できない

detect_zeroes は zero write の検出に関係し、unmap との組み合わせでは capacity 回収に使える場合があります。一方で検出処理には CPU cost があるため、要件と実測で判断します。

passthrough の性能と運用制約を交換する

NVMe や storage controller を PCI Passthrough で VM に渡すと、QEMU block layer や host filesystem を大きく迂回できます。その代わり、device の共有、snapshot、host 側監視、live migration、backup、障害交換の方法が変わります。

  • IOMMU group と device reset の対応
  • VM 停止中と障害時の device ownership
  • snapshot と backup をどの層で行うか
  • migration できない場合の maintenance 手順
  • SMART、firmware、temperature を誰が監視するか
  • 交換用 device と復旧時間を確保しているか

性能試験と障害試験を分けない

試験確認するもの
baselineIOPS、throughput、p50 / p95 / p99、CPU、queue
sync writefsync latency、flush、backend commit
mixed workloadread / write 比率と queue depth が本番に近いか
snapshot / backup通常 workload への latency 影響
capacity pressurethin pool、qcow2、filesystem の残量
failure / recoveryhost、backend、network 障害後の整合性と再開時間

benchmark は専用の test volume と再現可能な dataset で行います。本番 filesystem や active image に対して destructive な write test を実行しません。変更前の XML と測定値を保存し、1 変更ごとに同じ workload で比較します。

よくある誤判断

誤判断見落とすこと確認方法
qcow2 だから遅いchain、allocation、cache、backend経路ごとの latency を測る
writeback だから速くてよいflush と power loss 時の durability障害と recovery を試す
device utilization 100% だから限界並列 queue と完了 throughputlatency、queue、IOPS を一緒に見る
discard を有効にすれば回収できる途中の非対応層guest から backend まで追う
io_uring にすれば必ず速いversion、source type、workload同条件で AIO backend を比較する
passthrough なら問題が消えるbackup、migration、monitoring運用 lifecycle を評価する

まとめ

VM の storage I/O は、virtio、QEMU、image format、cache、host、backend の連続した経路です。raw / qcow2 や virtio-blk / virtio-scsi の名前だけで判断せず、同じ時間窓で latency、queue、throughput、error を対応付けます。

cache mode はデータ保護、discard は capacity 回収、IOThread と AIO は処理場所、passthrough は運用制約に関係します。性能試験と障害復旧を一組にし、変更を 1 つずつ比較することが、安全な storage I/O 設計の要点です。

関連する記事
VM ストレージ I/O 設計 – virtio / cache / qcow2 / backend を確認する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る