仮想ディスクがボトルネックになるとき
先月、会社のVMware vSphere 8.0クラスター全体のストレージレイヤーを見直す作業を終えた。きっかけは、データベース(MySQL、PostgreSQL)を動かしているVMが異常に高いI/O waitを継続的に報告していたことだ。CPU ready timeを確認しても問題なく、RAMも十分だったが、ディスクスループットはSANの理論値ベンチマークと比べて60〜70%程度しか出ていなかった。
datastore、HBAドライバー、RAIDポリシーなど、考えられる原因を一つひとつ排除していくうちに、該当するすべてのVMがLSI Logic SASアダプターを使っていることに気づいた。vSphereで新規VMを作成する際のデフォルト設定だ。これは実際のハードウェアをエミュレートするアダプターであり、それこそが問題の原因だった。
PVSCSI(Paravirtual SCSI)に切り替えることで、大部分の問題が解決した。CPU I/O処理は目に見えて低下し、スループットは期待通りのレベルまで向上した。この記事では、その過程を記録する。技術的な理由から実施手順、結果の測定方法まで順を追って説明する。
PVSCSIとLSI Logicの違い
LSI Logic SAS/BusLogicはエミュレートされたアダプターだ。VMkernelは実際のハードウェアデバイスの動作をすべて仮想的に再現する必要がある。ゲストOSからのI/O命令は、オーバーヘッドだらけのエミュレーション層を通過する——割り込みシミュレーション、レジスターエミュレーション、DMAマッピングの仮想化などだ。ゲストOSには特別なドライバーが不要で、実際のハードウェアと通信していると「思い込んでいる」ため、そのまま動作する。
PVSCSIはパラバーチャライズドアダプターだ。ゲストOSはVMware上で動作していることを認識しており、専用ドライバーを使って最適化されたプロトコルでVMkernelと直接通信する。エミュレーション層は存在しない。I/Oリクエストは直接VMkernelに渡るため、消費するCPUサイクルが大幅に削減される。
VMwareが公表したベンチマークによれば、I/O負荷の高いワークロードでは:
- I/O負荷の高いワークロードでCPUオーバーヘッドが約30〜50%削減
- シーケンシャル読み書きでスループットが最大20〜30%向上
- データベースワークロードでランダム4K IOPSが20〜40%改善(ストレージ構成による)
ただし、PVSCSIが常に優れているわけではない。静的なWebサーバーや軽いdev/test環境など、I/Oの少ないVMではほとんど差が出ない。PVSCSIが真価を発揮するのは、データベースサーバー、ファイルサーバー、CI/CDビルドパイプラインを継続的に実行するVMといった、I/O負荷の高いワークロードだ。
PVSCSIを使用するための条件
- VMware vSphere 4.0以上(またはVMware Workstation 6.5+)
- ゲストOS: RHEL/CentOS 5+、Ubuntu 10.04+、Windows Server 2003 SP2+(VMware Tools必須)、Windows Vista+(ビルトインドライバーあり)
- VMware Toolsがインストールされ、最新の状態であること
- 重要な注意点:Windows Server 2003、RHEL 4などの古いOSはブートイメージにPVSCSIドライバーが含まれていないため、PVSCSIをブートディスクとして使用する場合はドライバーの注入が必要
PVSCSIの設定 — 実践的なステップバイステップ
方法1:vSphere Client(GUI)でアダプターを変更する
1〜2台のVMには最も手軽な方法だ。VMは完全なPower Off状態である必要がある(Suspendではない)。
- VMを右クリック → Edit Settings
- SCSI Controller 0(または現在のアダプター)をクリック
- Change Typeドロップダウン → VMware Paravirtualを選択
- OKをクリック → VMをPower On
起動後、WindowsではDevice Managerを開いて「VMware PVSCSI Controller」を確認し、ドライバーが正しくロードされているかチェックする。Linuxの場合はlsmod | grep vmw_pvscsiで確認できる。
方法2:PowerCLIを使って複数のVMを一括変更する
10台以上のVMを手作業でやるのは半日仕事だ。PowerCLIなら数分で終わる:
# vCenterに接続
Connect-VIServer -Server vcenter.yourdomain.com
# 変更対象のVMリストを取得(例:「Production-DB」フォルダー内のすべてのVM)
$vms = Get-VM -Location (Get-Folder "Production-DB")
foreach ($vm in $vms) {
# 実行中のVMをスキップ
if ($vm.PowerState -ne "PoweredOff") {
Write-Warning "$($vm.Name) は実行中です。スキップします..."
continue
}
# PVSCSI以外のSCSIコントローラーを取得
$scsiCtrl = Get-ScsiController -VM $vm | Where-Object { $_.Type -ne "ParaVirtualSCSI" }
if ($scsiCtrl) {
Write-Host "$($vm.Name) のSCSIアダプターを変更しています..."
Set-ScsiController -ScsiController $scsiCtrl -Type ParaVirtualSCSI
Write-Host " 完了: $($vm.Name)" -ForegroundColor Green
} else {
Write-Host "$($vm.Name) はすでにPVSCSIを使用しています。スキップします。" -ForegroundColor Cyan
}
}
Disconnect-VIServer -Confirm:$false
実践的な注意点として、一度に全部Power Onしないこと。3〜5台ずつバッチ処理し、ログとディスクパフォーマンスを確認してから次に進もう。ドライバーの問題が発生した場合でも、すぐに気づけるし、何十台もまとめてではなく少数のVMだけロールバックすれば済む。
方法3:.vmxファイルを直接編集する(VMware Workstation / Fusion)
# VMの.vmxファイルを検索
find ~/vmware -name "*.vmx" | grep "VMName"
# ファイルを開いてscsi0.virtualDevの行を見つけ、以下を変更:
# scsi0.virtualDev = "lsisas1068"
# 変更後:
# scsi0.virtualDev = "pvscsi"
sed -i 's/scsi0.virtualDev = "lsisas1068"/scsi0.virtualDev = "pvscsi"/' /path/to/vm.vmx
その後、VMware Workstationを起動して通常通りVMをPower Onする。
変更後の確認 — Linuxゲストの場合
# PVSCSIドライバーがロードされているか確認
lsmod | grep vmw_pvscsi
# vmw_pvscsi 36864 4
# ディスクコントローラーの情報を確認
lspci | grep -i scsi
# VMware PVSCSI SCSI Controller
# ddコマンドでディスクの基本速度を確認
dd if=/dev/zero of=/tmp/test_io bs=1M count=1024 oflag=direct
# 1073741824 bytes (1.1 GB) copied, 2.84 s, 378 MB/s
fioを使った実際のベンチマーク
より正確に計測するために、I/Oベンチマークの標準ツールfioを使用した:
# fioのインストール
apt install fio # Ubuntu/Debian
yum install fio # CentOS/RHEL
# テスト1: シーケンシャル書き込み(ログ書き込み・バックアップを想定)
fio --name=seq-write \
--ioengine=libaio \
--rw=write \
--bs=1M \
--numjobs=4 \
--size=2G \
--runtime=60 \
--group_reporting \
--filename=/tmp/fio_test
# テスト2: ランダム4K読み込み(データベースIOPSを想定)
fio --name=rand-read \
--ioengine=libaio \
--rw=randread \
--bs=4k \
--iodepth=64 \
--numjobs=4 \
--size=2G \
--runtime=60 \
--group_reporting \
--filename=/tmp/fio_test
PostgreSQLを動かしているVM(vSphere 8.0、NVMeデータストア)での実際の比較結果:
- LSI Logic SAS:ランダム4K読み込み 〜85K IOPS、CPU I/O wait 〜12%
- PVSCSI:ランダム4K読み込み 〜118K IOPS、CPU I/O wait 〜6%
CPU waitが12%から6%に半減した——これが最も印象的だった。以前はCPUサイクルの半分がI/O待ちで「足止め」されていたことになる。解放されたリソースにより、PostgreSQLは実際のクエリ処理により多くのリソースを充てられるようになった。
Proxmoxの視点から — PVSCSIをより深く理解する
個人のラボ環境をVMwareからProxmoxに移行したとき、いくつかの興味深い違いに気づいた。ProxmoxはPVSCSIの代わりにVirtIO SCSIをパラバーチャルアダプターとして採用している。原理は同じだが実装が異なる。Proxmoxでも、VirtIOを有効にしていなければ、ディスクパフォーマンスはLSI LogicをエミュレートしているVMwareと同様に低下する。
得られた教訓:パラバーチャライゼーションは「VMware独自の機能」ではなく、すべての本格的なハイパーバイザーが実装すべきI/O最適化アーキテクチャだ。VMwareはそれをPVSCSIと呼び、KVM/ProxmoxはVirtIOと呼ぶ。本質は同じで、どちらもエミュレーションのオーバーヘッドという共通の問題を解決している。
PVSCSIへの変更を避けるべきケース
- ビルトインドライバーのない古いOSのブートディスク:Windows Server 2003、RHEL 4はブートディスクを変更する前に、WinPEまたはinitramfsにPVSCSIドライバーを注入する必要がある。この作業に慣れていない場合は、ブートディスクはLSI Logicのままにして、データディスクだけPVSCSIに変更する方が安全だ。
- I/Oの少ないテスト/開発用VM:静的なWebサーバーや軽い開発環境のためにダウンタイムをとってアダプターを変更する価値はない。
- メンテナンスウィンドウがない場合:SCSIアダプターの変更にはVMの完全なPower Offが必要だ。スケジュールを明確に設定し、事前に関係者へ通知すること。
まとめ
PVSCSIの魅力はここにある——追加のハードウェアも新しいライセンスも不要で、その存在を知って設定を一つ変えるだけでいい。それにもかかわらず、「デフォルトでそう設定されていたから、誰も変えなかった」という理由で、多くの本番環境がいまだにLSI Logicで動き続けている。
I/O負荷の高いワークロード(データベース、ビルドサーバー、VM内で動作するNFSサーバー)を持つVMwareクラスターを管理しているなら、SCSIアダプタータイプの監査を優先すべきだ。各VMのダウンタイムはわずか数分だが、モニタリングダッシュボード上で改善をすぐに確認できる。
最後のヒント:PVSCSI切り替え後は、キュー深度(queue depth)も確認すること。PVSCSIのデフォルトのキュー深度はLSI Logicより大きい(デバイスあたり256対32)。データストアに独自の制限がある場合、キューの飽和を防ぎ同じデータストアを共有する他のVMへの影響を避けるために、ESXiホストのDisk.SchedNumReqOutstandingパラメーターを追加チューニングする必要があるかもしれない。

