Proxmox PCI Resource Mapping 設定ガイド:Proxmox 8でラベルを使ってGPU・USB・NICをVMに柔軟に割り当てる方法

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

まさに自分がこの状況に遭遇しました。Proxmoxで12台のVMとコンテナを管理するhomelabで、GPUを接続したWindows VMをあるノードから別のノードに移行する必要が生じたのです。結果は?新しいノードではGPUカードのPCI IDがまったく異なるため、VMが起動できませんでした。手動でconfigを修正し、古いデバイスを削除して追加し直す作業に——本来なら自動化できるはずのことに30分近くかかりました。

それがProxmox 8が公式インターフェースにPCI Resource Mappingを導入した理由です。VM configにPCIアドレスをハードコードする代わりに、論理ラベル——たとえばgpu-rtx3060——を定義し、VMはそのラベルを宣言するだけです。実際のPCI IDはProxmoxが解決します。

従来のPCI Passthroughの問題点

Proxmoxで従来のPCI passthroughを行う場合、/etc/pve/qemu-server/<vmid>.confにあるVM configファイルを直接編集していました:

hostpci0: 0000:01:00.0,pcie=1,x-vga=1

0000:01:00.0はそのホスト上のGPUカードの物理的なPCI IDです。これはハードコードされています。同じ種類のGPUを搭載した別のノードにVMを移行しても、そのノードのPCI IDが0000:03:00.0であれば——デバイスが見つからないため、VMは起動時すぐにエラーを報告します。

複数ノードのクラスターではさらに深刻です。各マシンのハードウェアが異なり、挿すスロットも違うため、PCI IDに規則性はありません。一度でも誤って移行してしまえば、この方法がスケールアップに向かない理由がよく分かります。

コアコンセプト:Resource Mappingとは?

PCI Resource Mapping(Device Mappingとも呼ばれます)は、VM configと物理ハードウェアの間に位置する抽象化レイヤーです。gpu-rtx3060のような明確な名前でマップエントリを定義し、クラスター内の各ノードに対してその名前に対応するデバイスを指定します。

GPUが必要なVMはマッピングgpu-rtx3060を宣言するだけで、Proxmoxが実行中のノードに適切なPCI IDを自動的に解決します。別のノードに移行しても?VM configは一切変更不要です。

Proxmox 8は2種類のデバイスのマッピングをサポートしています:

  • PCIデバイス:GPU、NIC、サウンドカード、ストレージコントローラーなど
  • USBデバイス:USBドングル、USB-to-serial、Webカメラ、セキュリティデバイスなど

実践:Proxmox 8でのPCI Resource Mapping設定

ステップ1:各ノードのデバイスのPCI IDを確認する

各Proxmoxノードにsshして、PCIデバイスを一覧表示します:

# すべてのPCIデバイスを表示
lspci

# GPUをフィルタリング
lspci | grep -i vga
lspci | grep -i nvidia

# NICをフィルタリング
lspci | grep -i ethernet

# 特定のデバイスの詳細を表示(IDを適宜変更)
lspci -v -s 01:00.0

node-1での出力例:

01:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
01:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller

node-2では同じGPUカードですが、異なるスロットに挿しています:

03:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]
03:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller

ステップ2:Proxmox Web UIでResource Mappingを作成する

左サイドバーのDatacenter → Resource Mappingsにアクセスします——このメニューはProxmox 8.0から追加されたもので、バージョン7には存在しません。

PCI DevicesタブでAddをクリックします:

  • Name:わかりやすい名前を付けます(例:gpu-rtx3060nic-10g-mellanox
  • Node:node-1を選択
  • Device ID0000:01:00を入力(デバイス全体をマッピングする場合、ファンクション番号は不要)
  • Sub-device:GPUにオーディオコントローラーが付属している場合、0000:01:00.1をここに追加

node-1を追加した後、Add Nodeをクリックして、対応するID(0000:03:00)でnode-2を追加します。Proxmoxはデバイスの互換性を検証します——ノード間でベンダーIDとデバイスIDが一致する必要があります。

ステップ3:USB Mappingを作成する(USBドングルやシリアルデバイス用)

USB Devicesタブに切り替えて、Addをクリックします:

# ホスト上のUSBデバイスを検索
lsusb

# 出力例:
# Bus 001 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial
# Bus 002 Device 004: ID 1a2b:0001 Dongle Corp License Dongle

UIにVendor ID0403)とDevice ID6001)を入力します。ProxmoxはUSBデバイスを物理ポートではなくハードウェアIDで照合するため、再起動後に別のポートに挿し直しても正しくデバイスを認識します。

ステップ4:VMにResource Mappingを割り当てる

設定するVMに移動し、HardwareAddPCI Deviceを選択します。

ドロップダウンでRaw Deviceの代わりにMapped Deviceを選択します。作成済みのマッピング一覧が表示されます。gpu-rtx3060を選択し、追加設定を行います:

  • PCIe:カードが対応している場合は有効にする(最新のGPUのほとんどが対応)
  • Primary GPU:全ディスプレイ出力をpassthroughしたい場合は有効にする
  • All Functions:GPUに付属するオーディオコントローラーも一緒にpassするために有効にする

ステップ5:CLIで設定する(自動化向け)

多数のVMを管理する場合やスクリプト化したい場合は、pveshを直接使用します:

# API経由でPCIマッピングを作成
pvesh create /cluster/mapping/pci \
  --id gpu-rtx3060 \
  --description "NVIDIA RTX 3060" \
  --map node=node-1,path=0000:01:00,id=10de:2504 \
  --map node=node-2,path=0000:03:00,id=10de:2504

# 作成済みマッピングの一覧を表示
pvesh get /cluster/mapping/pci

# 特定のマッピングの詳細を表示
pvesh get /cluster/mapping/pci/gpu-rtx3060

マッピングを作成したら、qmでVMに割り当てます:

# VM ID 101にPCIマッピングを割り当て
qm set 101 --hostpci0 mapping=gpu-rtx3060,pcie=1,x-vga=1

# USBマッピングを割り当て
qm set 101 --usb0 mapping=usb-dongle

# VMの現在のconfigを表示
qm config 101

割り当て後のVM configファイルはとてもすっきりしています——PCI IDのハードコードがありません:

hostpci0: mapping=gpu-rtx3060,pcie=1,x-vga=1
usb0: mapping=usb-dongle

ステップ6:確認とデバッグ

VMを起動する前に、IOMMUが有効になっていることを確認します——これはResource Mappingに限らず、すべてのPCI passthroughの前提条件です:

# ホストのIOMMUを確認
dmesg | grep -e DMAR -e IOMMU

# IOMMUグループを表示(各グループは一緒にpassthroughする必要がある)
for d in /sys/kernel/iommu_groups/*/devices/*; do
  n=${d#*/iommu_groups/*}; n=${n%%/*}
  printf 'IOMMU Group %s ' "$n"
  lspci -nns "${d##*/}"
done

GPUが独立したIOMMUグループに属していない場合(他のデバイスとグループを共有している場合)、カーネルパラメーターでpcie_acs_overrideを有効にする必要があります——ただしそれは別のトピックです。

VMを起動した後、ProxmoxのlogにどのデバイスがResolveされたかが明確に表示されます:

# VMのlogを表示
journalctl -u qmeventd --since "5 minutes ago"

# またはタスクlogを直接表示
tail -f /var/log/pve/tasks/active

homelabからの実践的な注意点

自分のhomelabではProxmox VEで12台のVMとコンテナを管理しています——productionに移す前に何でもテストするための環境です。Resource Mappingに切り替えてから、いくつか気をつけるべき点に気づきました:

  • マッピング作成時の検証:Proxmoxはノード間のベンダーIDとデバイスIDを確認します。node-1にRTX 3060をマッピングし、node-2がGTX 1080(IDが異なる)の場合——警告は表示されますが通過は許可されます。node-2でVMを起動するとエラーになります。ハードウェアが実際に同じであることを確認してください。
  • USBマッピングはポート指定より安定:以前は物理ポートでusb0: host=2-1.3を使用していましたが、再起動や再挿入するとVMがデバイスを見失いました。ベンダー+デバイスIDでのマッピングによりこの問題は完全に解決しました。
  • pfSense/OPNsenseへのNIC passthrough:10G NICのマッピングを作成してファイアウォールVMに割り当てることで、ノード間での移行時にVMのネットワーク設定を変更する必要がなくなりました。
  • MIGを使ったGPU共有:Resource MappingはUIからNVIDIA MIGパーティションをまだサポートしていません。A100/H100をMIGで使用する場合は、引き続き手動での設定が必要です。

まとめ

PCI Resource MappingはProxmoxクラスターユーザーが長らく待ち望んでいた機能です。シンプルなアイデア:VMはgpu-rtx3060というラベルを宣言するだけで、物理的なPCI IDが何であるか、どのノードにあるかを気にする必要はありません。Proxmoxがその解決を担います。

クラスターにノードを追加する際は、既存のラベルに新しいデバイスをマッピングするだけで完了です。深夜2時にVMを移行する際も、眠い目をこすりながらconfigを修正する必要はありません。初回使用時から実感できる、まさにそういった改善です。

まだProxmox 7でPCI IDをハードコードしているなら——これはバージョン8へのアップグレードを検討するのに十分な理由です。

Share: