物理ディスク並みの高速さ:KVM共有フォルダをvirtiofsで設定する方法

Virtualization tutorial - IT technology blog
Virtualization tutorial - IT technology blog

なぜvirtiofsがKVM仮想マシンの「最適解」なのか?

KVMを長期間運用していると、ホストから仮想マシンにいかに速くデータを転送するかという悩みに必ず直面します。以前は、定番の解決策として9p (Plan 9) が使われていました。しかし、9pの速度は正直なところ不十分です。10,000個のソースコードファイルを含むディレクトリでテストした際、9pではインデックス作成に約2分かかりましたが、virtiofsならわずか5秒足らずで完了しました。

Proxmoxのホームラボで何度もベンチマークを行った結果、virtiofsが最良の選択肢であると断言できます。これは複雑なネットワークプロトコルをエミュレートするのではなく、共有メモリ(shared memory)を使用して、仮想マシンがホストのファイルシステムに直接アクセスできるようにします。実際のパフォーマンスは物理ディスクの90〜95%に達することもあり、NFSや9pの30〜40%という数値を大きく上回ります。

開始前の「道具」の準備

virtiofsをスムーズに動作させるには、ホストとゲストの両方が対応している必要があります。以下の要件を確認してください:

  • Host OS: カーネル 5.4 以降。Ubuntu 20.04 や Debian 11 であれば問題なく動作します。
  • QEMU: バージョン 4.2 以降が必須です。
  • Guest OS: Linux カーネル 5.4 以降、または Windows の場合は追加のドライバーが必要です。
  • virtiofsd: I/Oを処理するデーモン。Ubuntuでは qemu-system-common パッケージをインストールしてください。

詳細な設定手順

ステップ 1: 共有メモリ (Shared Memory) の設定

これは非常に重要なステップです。virtiofsでは、ホストとゲストが共にアクセスできるよう、仮想マシンのメモリを “shared” としてマークする必要があります。

仮想マシンのXML設定ファイルを開きます:

virsh edit <仮想マシン名>

<domain> タグの直下に以下のコードを追加します:

<memoryBacking>
  <source type='memfd'/>
  <access mode='shared'/>
</memoryBacking>

RAMの最適化のためにHugepagesを使用している場合は設定が少し異なりますが、一般的な用途では memfd が最も安定した選択肢です。

ステップ 2: 仮想マシンに Filesystem デバイスを追加する

引き続きXMLファイル内で、<devices> タグを探します。共有したいディレクトリをここで定義します:

<filesystem type='mount' accessmode='passthrough'>
  <driver type='virtiofs'/>
  <source dir='/path/to/host/folder'/>
  <target dir='my_shared_tag'/>
</filesystem>

各パラメータの注意点:

  • source dir: ホストマシン上の絶対パス。
  • target dir: マウント時に呼び出すための「タグ (tag)」。スペースを含まない短い名前を付けてください。
  • accessmode='passthrough': ホストからゲストへ、ファイルの所有権 (UID/GID) をそのまま維持します。

ステップ 3: ゲスト仮想マシンでディレクトリをマウントする

XMLを保存して仮想マシンを再起動します。次に、ゲストにログインしてディスクをマウントします。

マウント先となるディレクトリを作成します:

sudo mkdir -p /mnt/shared_data

マウントコマンドを実行します:

sudo mount -t virtiofs my_shared_tag /mnt/shared_data

再起動時に自動的にマウントされるようにするには、/etc/fstab ファイルの末尾に以下の行を追加します:

my_shared_tag  /mnt/shared_data  virtiofs  defaults  0  0

権限エラーの解決 – 定番の悩み

「ファイルは見えているのに書き込めない」というのは、90%の人が遭遇するエラーです。原因は、ホストとゲストのユーザーID (UID) が一致していないことにあります。

開発環境であれば、手っ取り早い方法はソースディレクトリに 777 権限を設定することです。しかし、本番環境では安全ではありません。より適切な方法は、ps aux | grep qemu コマンドでQEMUプロセスを実行しているユーザーを確認することです。通常は libvirt-qemu ユーザーです。このユーザーがホスト上のソースディレクトリに対して読み取り/書き込み権限を持っていることを確認してください。

ラボからの実践的な経験

12台のVMでvirtiofsを6ヶ月間運用した結果、3つの重要な注意点を見つけました:

  1. 重いデータベースでの使用を避ける: 高速ではありますが、virtiofsは標準の仮想ディスク (qcow2) よりもI/O遅延が大きくなります。MySQLやPostgreSQLの場合は、データの整合性を確保するために仮想ディスクを優先してください。
  2. AppArmor/SELinux: VMが起動しない場合はログを確認してください。多くの場合、AppArmorがQEMUによる外部ディレクトリへのアクセスをブロックしています。/etc/apparmor.d/abstractions/libvirt-qemu でソースディレクトリを許可する必要があります。
  3. 小さなファイルの処理: virtiofsは node_modulesvendor などの処理に非常に強力です。npm install コマンドの実行速度は、NFSを使用する場合に比べて5倍以上速くなります。

まとめ

virtiofsは、ホストとゲストの間の速度の壁を取り払います。設定はそれほど難しくありませんが、ワークフローにもたらす効果は絶大です。もし今でもSambaやNFSで苦労しているなら、今日からvirtiofsに切り替えましょう。

設定がうまくいくことを願っています。権限設定やAppArmorで詰まったら、下のコメント欄に残してください。サポートします!

Share: