Virtuelle Umgebung mit OpenStack
OpenStack ist ein weit verbreitetes Produkt zur Realisierung einer virtuellen Umgebung. Diese arbeitet im Standard mit QEMU/KVM als Hypervisor. Kolla packt die OpenStack Komponenten in Container. In dieser Kombination ist ein Aufbau mit einer handelsüblichen Nvidia Grafikkarte wie unten beschrieben möglich. Dazu wird mindestens ein Hypervisor mit passendem PCI Slot, Nvidia Grafikkarte und ausreichend Platz im Gehäuse benötigt.
Hardware
- HP ProLiant DL380 Gen9
- Intel(R) Xeon(R) CPU E5-2678
- 192 GB RAM
- GeForce RTX 2080 Ti
- Ubuntu 18.04.2 (Hypervisor)
- Ubuntu 16.04 (Instanz)
- CUDA 10.2
Grafikkarte
Sobald die Karte in einem passenden Server (Bauhöhe) verbaut und dieser als Hypervisor in OpenStack aufgenommen wurde, kann es auch schon losgehen. Um an die für die weitere Konfiguration notwendigen Infos zu gelangen, gehen Sie wie folgt vor:
- PCI Adresse der Grafikkarte
$ lspci | grep NVIDIA
84:00.0 VGA compatible controller: NVIDIA Corporation GV102 (rev a1)
84:00.1 Audio device: NVIDIA Corporation Device 10f7 (rev a1)
84:00.2 USB controller: NVIDIA Corporation Device 1ad6 (rev a1)
84:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad7 (rev a1)
$ lshw -numeric -C display
[...]
*-display
description: VGA compatible controller
product: GV102 [10DE:1E07]
vendor: NVIDIA Corporation [10DE]
[...]
Hier sind die Werte 10DE:1E07
, 10DE:10F7
, 10DE:1AD6
, 10DE:1AD7
und 84:00.0
, 84:00.1
wichtig. Die ersten vier Werte werden im weiteren Verlauf benötigt. Mit den beiden letzten Werten fragen wir nach den verwendeten Treibern.
- verwendete Treiber
$ lspci -kk -s 84:00.1
84:00.1 Audio device: NVIDIA Corporation Device 10f7 (rev a1)
Subsystem: Gigabyte Technology Co., Ltd Device 37a9
Kernel driver in use: snd_hda_intel
Kernel modules: snd_hda_intel
$ lspci -kk -s 84:00.0
84:00.0 VGA compatible controller: NVIDIA Corporation GV102 (rev a1)
Subsystem: Gigabyte Technology Co., Ltd Device 37a9
Kernel driver in use: nouveau
Kernel modules: nvidiafb, nouveau
...
Hierbei ist die Zeile Kernel driver in use
und die Einträge snd_hda_intel
und nouveau
darin wichtig. Sie beschreiben den Treiber, der vom Kernel verwendet wird, um mit dieser Hardware zu sprechen. Später übergeben sie sie dem Kernel, sodass diese Treiber nicht mehr geladen werden.
IOMMU
Mit dem folgenden Befehl fragen Sie ab, ob IOMMU
aktiviert ist:
$ virt-host-validate
[...]
QEMU: Checking for device assignment IOMMU support : PASS
QEMU: Checking if IOMMU is enabled by kernel : PASS
[...]
Finden Sie folgende Ausgabe vor
$ virt-host-validate
[...]
QEMU: Checking for device assignment IOMMU support : PASS
QEMU: Checking if IOMMU is enabled by kernel : WARN (IOMMU appears to be disabled in kernel. Add intel_iommu=on to kernel cmdline arguments)
[...]
setzen Sie für AMD Prozessoren die folgenden Optionen in Kolla
und diese Optionen für Prozessoren von Intel:
Treiberzugriff auf Host unterbinden
Deaktivieren Sie den geladenen Treiber der Grafikkarte:
In unserem Beispiel ist eine Soundkarte in der Grafikkarte, die Sie wie folgt deaktivieren:
$ cat /etc/modprobe.d/blacklist-nvidia-nouveau.conf
blacklist snd_hda_intel
blacklist nouveau
options nouveau modeset=0
Abschließend aktualisieren Sie die Initramfs und starten den Server neu:
PCI Passthrough
Für die Passthrough-Konfiguration übergeben Sie die oben ermittelten PCI-Adressdaten an das Kernelmodul vfio
.
In unserem Beispiel hat die Grafikkarte mehrere Komponenten, dann sieht die Konfiguration wie folgt aus:
$ cat /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:1e07,10de:10f7,10de:1ad6,10de:1ad7
options vfio-pci disable_vga=1
Nun aktivieren Sie das Kernelmodul vfio
:
zudem muss im Nova Scheduler
der ‘PciPassthroughFilter’ aktiviert und ausgerollt werden.
$ cat kolla/files/overlays/nova/nova-scheduler.conf
[filter_scheduler]
enabled_filters = ..., PciPassthroughFilter
Nun noch die Informationen für Nova konfigurieren:
$ cat kolla/files/overlays/nova/nova-api.conf
[pci]
alias = { "vendor_id":"10de", "product_id":"1e07", "device_type":"type-PCI", "name":"nvidia" }
$ cat kolla/files/overlays/nova/nova-compute.conf
[pci]
alias = { "vendor_id":"10de", "product_id":"1e07", "device_type":"type-PCI", "name":"nvidia" }
passthrough_whitelist = { "vendor_id": "10de", "product_id": "1e07" }
Ist nur ein Hypervisor mit einer Grafikkarte ausgestattet, wird Nova Compute auch nur auf diesem Hypervisor konfiguriert:
$ cat kolla/files/overlays/nova/gpuserver/nova.conf
[pci]
alias = { "vendor_id":"10de", "product_id":"1e07", "device_type":"type-PCI", "name":"nvidia" }
passthrough_whitelist = { "vendor_id": "10de", "product_id": "1e07" }
Bei unserer Grafikkarte sind mehrere Geräte in der Karte verbaut und wenn all diese durchgereicht werden sollen, sieht die Konfiguration so aus:
$ cat kolla/files/overlays/nova/nova-api.conf
[pci]
alias = { "vendor_id":"10de", "product_id":"1e07", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"10f7", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"1ad6", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"1ad7", "device_type":"type-PCI", "name":"nvidia" }
$ cat kolla/files/overlays/nova/gpuserver/nova.conf
[pci]
alias = { "vendor_id":"10de", "product_id":"1e07", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"10f7", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"1ad6", "device_type":"type-PCI", "name":"nvidia" }
alias = { "vendor_id":"10de", "product_id":"1ad7", "device_type":"type-PCI", "name":"nvidia" }
passthrough_whitelist = [{ "vendor_id":"10de", "product_id":"1e07" },
{ "vendor_id":"10de", "product_id":"10f7" },
{ "vendor_id":"10de", "product_id":"1ad6" },
{ "vendor_id":"10de", "product_id":"1ad7" }]
OpenStack Flavor
Nachdem Sie die OpenStack Nova Konfiguration ausgerollt haben, fehlt noch ein OpenStack Flavor, das Sie mit folgendem Befehl anlegen:
Die Zahl bei nvidia:1
beschreibt die Anzahl der durchzureichenden Geräte-Komponenten, folglich ist diese in unserem Beispiel 4 und damit ist der Befehl:
Hypervisor verstecken
Zum Schluss muss der Hypervisor “versteckt” werden. Dies ist notwendig, damit der nvidia
Treiber später auch in der virtuellen Maschine geladen wird und die Grafikkarte ansteuern kann. Ohne diesen Trick funktioniert das Ganze nicht und die Grafikkarte wird vom Treiber “ignoriert”.
Virtuelle Maschine
Neben den GPU Treibern auf der Download-Seite des Herstellers [1], existiert mit CUDA ein spezielles Toolkit von Nvidia [2], das u.a. auch das nvidia
Treiber Binary mit an Bord hat. Nach der Auswahl für Operating System
, Architecture
, Distribution
und Distributions-Version
wählen Sie den Installer Type
(runfile(local), deb(local), deb(network) und cluster(local)) aus. Details zur Installation des CUDA
Toolkits finden Sie hier [3].
CUDA installieren
Nachdem Sie CUDA mit dem runfile(local)
installiert haben
$ sudo sh cuda_<cudaversion>_<gpudriverversion>_linux.run
===========
= Summary =
===========
Driver: Installed
Toolkit: Installed in /usr/local/cuda-10.2/
Samples: Installed in /root/, but missing recommended libraries
Please make sure that
- PATH includes /usr/local/cuda-10.2/bin
- LD_LIBRARY_PATH includes /usr/local/cuda-10.2/lib64, or, add /usr/local/cuda-10.2/lib64 to /etc/ld.so.conf and run ldconfig as root
To uninstall the CUDA Toolkit, run cuda-uninstaller in /usr/local/cuda-10.2/bin
To uninstall the NVIDIA Driver, run nvidia-uninstall
Please see CUDA_Installation_Guide_Linux.pdf in /usr/local/cuda-10.2/doc/pdf for detailed information on setting up CUDA.
Logfile is /var/log/cuda-installer.log
und die Anpassungen an $PATH
und für ld
vorgenommen haben, verifizieren Sie die korrekte Zusammenarbeit von Treiber in der virtuellen Maschine und Grafikkarte auf dem Host an folgenden Stellen:
- Im
proc
Verzeichnis sehen Sie die Version des Kernelmoduls für Nvidia
$ cat /proc/driver/nvidia/version
NVRM version: NVIDIA UNIX x86_64 Kernel Module 440.33.01 Wed Nov 13 00:00:22 UTC 2019
GCC version: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)
- Sie müssen drei Geräte unter
dev
sehen
$ ls -l /dev/nvidia*
crw-rw-rw- 1 root root 195, 0 Mar 4 16:49 /dev/nvidia0
crw-rw-rw- 1 root root 195, 255 Mar 4 16:49 /dev/nvidiactl
crw-rw-rw- 1 root root 244, 0 Mar 4 16:49 /dev/nvidia-uvm
- Zuletzt sehen Sie mit
nvidia-smi
die Informationen zur Grafikkarte
$ nvidia-smi
Tue Mar 24 11:44:44 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.33.01 Driver Version: 440.33.01 CUDA Version: 10.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce RTX 208... Off | 00000000:00:08.0 Off | N/A |
| 0% 55C P0 53W / 300W | 0MiB / 11019MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
- Mit dem Toolkit CUDA werden Samples mitgeliefert, die nach einem
make
für einen ersten Test zur Verfügung stehen, weitere Informationen finden Sie unter [4].
$ cd ~/NVIDIA_CUDA-10.2_Samples
$ make
~/NVIDIA_CUDA-10.2_Samples/bin/x86_64/linux/release/deviceQuery
~/NVIDIA_CUDA-10.2_Samples/bin/x86_64/linux/release/bandwithTest
Blick in die Zukunft
Es ist nicht ausgeschlossen, dass das hier beschriebene Vorgehen in einer zukünftigen Version des Treibers nicht funktioniert.
Nachtrag (14.4.2021)
Seit dem 30. März 2021 hat Nvidia einen Windows-Treiber im Program (Version 465.89), welcher das Durchreichen nun offiziell unterstützt. Nähere Informationen finden sich hier.