Mình đã gặp đúng cái tình huống này: homelab chạy Proxmox với 12 VM và container, một hôm cần chuyển VM Windows có gắn GPU từ node này sang node khác. Kết quả? VM không boot được vì PCI ID của card GPU trên node mới khác hoàn toàn. Phải vào sửa tay config, xoá thiết bị cũ, thêm lại — mất gần 30 phút cho một việc đáng lẽ phải tự động.
Đó là lý do Proxmox 8 đưa PCI Resource Mapping vào giao diện chính thức. Thay vì bind cứng địa chỉ PCI vào config VM, bạn định nghĩa một nhãn logic — kiểu như gpu-rtx3060 — và VM chỉ khai báo nhãn đó. PCI ID thực tế? Proxmox lo.
Vấn đề với PCI Passthrough truyền thống
Cách cũ khi làm PCI passthrough trên Proxmox là edit trực tiếp file config của VM tại /etc/pve/qemu-server/<vmid>.conf:
hostpci0: 0000:01:00.0,pcie=1,x-vga=1
Địa chỉ 0000:01:00.0 là PCI ID vật lý của card GPU trên host đó. Nó bị hard-code. Migrate VM sang node khác mà node kia có cùng loại GPU nhưng PCI ID là 0000:03:00.0 — VM báo lỗi ngay lúc start vì không tìm thấy thiết bị.
Cluster nhiều node còn tệ hơn: mỗi máy hardware khác, slot cắm khác, PCI ID không có quy luật nào. Một lần migrate nhầm là đủ để hiểu tại sao cách này không ổn khi scale lên.
Khái niệm cốt lõi: Resource Mapping là gì?
PCI Resource Mapping (hay Device Mapping) là một lớp trừu tượng nằm giữa VM config và hardware vật lý. Bạn định nghĩa một map entry với tên gọi rõ ràng, ví dụ gpu-rtx3060, rồi chỉ định cho từng node trong cluster thiết bị nào tương ứng với tên đó.
VM nào cần GPU thì khai báo dùng mapping gpu-rtx3060 — Proxmox tự resolve ra PCI ID thích hợp cho node đang chạy. Migrate sang node khác? Config VM không đổi một chữ.
Proxmox 8 hỗ trợ mapping cho hai loại thiết bị:
- PCI Device: GPU, NIC, sound card, storage controller…
- USB Device: USB dongle, USB-to-serial, webcam, thiết bị bảo mật…
Thực hành: Cấu hình PCI Resource Mapping trên Proxmox 8
Bước 1: Xác định PCI ID của thiết bị trên từng node
SSH vào từng node Proxmox và liệt kê thiết bị PCI:
# Xem toàn bộ thiết bị PCI
lspci
# Lọc GPU
lspci | grep -i vga
lspci | grep -i nvidia
# Lọc NIC
lspci | grep -i ethernet
# Xem chi tiết một thiết bị (thay ID phù hợp)
lspci -v -s 01:00.0
Ví dụ output trên 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
Trên node-2, cùng card GPU nhưng cắm ở slot khác:
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
Bước 2: Tạo Resource Mapping qua Proxmox Web UI
Truy cập Datacenter → Resource Mappings trong sidebar trái — mục này xuất hiện từ Proxmox 8.0, không có trong phiên bản 7.
Click Add trong tab PCI Devices:
- Name: đặt tên rõ ràng, ví dụ
gpu-rtx3060hoặcnic-10g-mellanox - Node: chọn node-1
- Device ID: nhập
0000:01:00(không cần function number nếu muốn map toàn bộ device) - Sub-device: nếu GPU có audio controller đi kèm, thêm
0000:01:00.1vào đây
Sau khi thêm node-1, click Add Node để thêm node-2 với ID tương ứng (0000:03:00). Proxmox sẽ validate xem thiết bị có compatible không — vendor ID và device ID phải khớp giữa các node.
Bước 3: Tạo USB Mapping (cho USB dongle hoặc thiết bị serial)
Chuyển sang tab USB Devices, click Add:
# Tìm USB device trên host
lsusb
# Output mẫu:
# 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
Điền Vendor ID (0403) và Device ID (6001) vào UI. Proxmox match USB device theo hardware ID chứ không phải port vật lý — cắm vào cổng khác sau reboot vẫn nhận đúng thiết bị.
Bước 4: Gán Resource Mapping cho VM
Vào VM cần cấu hình → Hardware → Add → PCI Device.
Ở dropdown, chọn Mapped Device thay vì Raw Device. Bạn sẽ thấy list các mapping đã tạo. Chọn gpu-rtx3060 và cấu hình thêm:
- PCIe: bật nếu card hỗ trợ (hầu hết GPU hiện đại)
- Primary GPU: bật nếu muốn passthrough toàn bộ display output
- All Functions: bật để pass cả audio controller đi kèm GPU
Bước 5: Cấu hình qua CLI (cho automation)
Quản lý nhiều VM hoặc muốn script hóa thì dùng pvesh trực tiếp:
# Tạo PCI mapping qua API
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
# Xem danh sách mapping đã tạo
pvesh get /cluster/mapping/pci
# Xem chi tiết một mapping
pvesh get /cluster/mapping/pci/gpu-rtx3060
Sau khi tạo mapping, gán vào VM qua qm:
# Gán PCI mapping cho VM ID 101
qm set 101 --hostpci0 mapping=gpu-rtx3060,pcie=1,x-vga=1
# Gán USB mapping
qm set 101 --usb0 mapping=usb-dongle
# Xem config hiện tại của VM
qm config 101
Config file VM sau khi gán trông gọn hơn nhiều — không còn hard-code PCI ID:
hostpci0: mapping=gpu-rtx3060,pcie=1,x-vga=1
usb0: mapping=usb-dongle
Bước 6: Kiểm tra và debug
Trước khi start VM, xác nhận IOMMU đã được bật — đây là điều kiện tiên quyết cho mọi PCI passthrough, không phải riêng Resource Mapping:
# Kiểm tra IOMMU trên host
dmesg | grep -e DMAR -e IOMMU
# Xem IOMMU groups (mỗi group phải passthrough cùng nhau)
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done
Nếu GPU không nằm trong IOMMU group riêng biệt (chung group với thiết bị khác), cần bật pcie_acs_override trong kernel parameter — nhưng đó là chủ đề khác.
Sau khi start VM, log Proxmox hiện rõ thiết bị nào được resolve:
# Xem log của VM
journalctl -u qmeventd --since "5 minutes ago"
# Hoặc xem task log trực tiếp
tail -f /var/log/pve/tasks/active
Một số lưu ý thực tế từ homelab
Mình chạy homelab với Proxmox VE quản lý 12 VM và container — playground để test mọi thứ trước khi đưa lên production. Sau khi chuyển sang dùng Resource Mapping, có vài điểm cần lưu ý:
- Validation ngay lúc tạo mapping: Proxmox check vendor ID và device ID giữa các node. Map RTX 3060 ở node-1 nhưng node-2 lại là GTX 1080 (ID khác) — nó warn nhưng vẫn cho qua. VM start ở node-2 sẽ lỗi. Cần đảm bảo hardware thực sự giống nhau.
- USB mapping ổn định hơn by-port: Trước đây dùng
usb0: host=2-1.3theo port vật lý, reboot hoặc cắm lại là VM mất thiết bị. Mapping by vendor+device ID fix hoàn toàn vấn đề đó. - NIC passthrough cho pfSense/OPNsense: Tạo mapping cho NIC 10G, gán cho VM firewall — migrate giữa các node không cần đụng đến network config của VM nữa.
- GPU sharing với MIG: Resource Mapping hiện chưa hỗ trợ NVIDIA MIG partition qua UI. Dùng A100/H100 với MIG vẫn phải config thủ công.
Kết luận
PCI Resource Mapping là thứ dân Proxmox cluster đã cần từ lâu. Ý tưởng gọn: VM chỉ khai báo nhãn gpu-rtx3060, không cần quan tâm PCI ID vật lý là gì hay ở node nào. Proxmox lo phần resolve đó.
Thêm node vào cluster? Map thiết bị mới vào label có sẵn là xong. Migrate VM lúc 2 giờ sáng? Không cần ngồi sửa config trong khi đang buồn ngủ. Đây đúng là kiểu cải tiến mà người dùng cảm nhận được ngay lần đầu dùng.
Nếu bạn vẫn đang hard-code PCI ID trên Proxmox 7 — đây là lý do đủ mạnh để cân nhắc upgrade lên bản 8.
