NVidia Proxmox + LXC
Не так давно мне потребовалось добавить поддержку перекодировки в Plex, используя видеокарту. У меня уже был сервер Plex, который работал внутри Docker. Сам Docker стоял внутри LXC контейнера Proxmox. Перерыв кучу материалов и потратив не мало времени, решил сделать руководство.
Я предполагаю, что уже настроен хост Proxmox и LXC. Работает под управлением Debian 11 (Bullseye). В моем примере я буду запускать контейнер LXC с именем plex(ID 101) на моем хосте Proxmox. Все команды через терминал, без использования графического интерфейса. LXC получит привилегию fuse=1,nesting=1
набора функций. В качестве видеокарты я буду использовать Nvidia GeForce 1050Ti. Все команды будут выполняться как root.
Запуск в rootless LXC
Обратите внимание, что могут потребоваться другие шаги, если вы попытаетесь запустить это в контейнере LXC без root-прав или непривилегированном.
Proxmox хост
Первый шаг - это установка драйверов на хост. Хотя у Nvidia и есть официальный репозиторий Debian, который мы могли бы использьваоть, делать этого не будем. Потому что это может создать проблему - позднее нужно будет поставить в контейнер LXC драйверы, но без модулей ядра. Сделать это используя официальный репозиторий Debian я не смог. Поэтому будем устанавливать драйверы вручную. Другая проблема использования официального репозитория Debian - драйвер на хосте и в контейнере должны быть одной версии.
Для начала нужно отключить модуль ядра Nouveau, прежде чем сможем установить драйверы NVIDIA
echo -e "blacklist nouveau\noptions nouveau modeset=0" > /etc/modprobe.d/blacklist-nouveau.conf
update-initramfs -u
reboot
apt install build-essential
pve-headers-$(uname -r)
apt install proxmox-headers-$(uname -r)
Скачиваем и устанавливаем драйвер nvidia. 550.54.14 был последним на момент написания статьи.
wget -O NVIDIA-Linux-x86_64-550.54.14.run https://ru.download.nvidia.com/XFree86/Linux-x86_64/550.54.14/NVIDIA-Linux-x86_64-550.54.14.run
chmod +x NVIDIA-Linux-x86_64-550.54.14.run
./NVIDIA-Linux-x86_64-550.54.14.run --check
./NVIDIA-Linux-x86_64-550.54.14.run
Tip
При установке, будет выбор что ставить дополнительно. В пунктах, перечисленных ниже, нужно ответить No
- install 32bit compability drivers
- should update X config
После установки драйверов нужно добавить несколько правил udev. Это необходимо для того, чтобы гарантировать загрузку правильных модулей ядра и создание всех соответствующих файлов устройств при загрузке.
echo -e '\n# load nvidia modules\nnvidia-drm\nnvidia-uvm' >> /etc/modules-load.d/modules.conf
/etc/udev/rules.d/70-nvidia.rules
- создаст соответствующие файлы устройств в /dev/
во время загрузки
KERNEL=="nvidia", RUN+="/bin/bash -c '/usr/bin/nvidia-smi -L && /bin/chmod 666 /dev/nvidia*'"
KERNEL=="nvidia_uvm", RUN+="/bin/bash -c '/usr/bin/nvidia-modprobe -c0 -u && /bin/chmod 0666 /dev/nvidia-uvm*'"
SUBSYSTEM=="module", ACTION=="add", DEVPATH=="/module/nvidia", RUN+="/usr/bin/nvidia-modprobe -m"
Копируем и извлекаем.
cp /usr/share/doc/NVIDIA_GLX-1.0/samples/nvidia-persistenced-init.tar.bz2 .
bzip2 nvidia-persistenced-init.tar.bz2
tar -xf nvidia-persistenced-init.tar
rm /etc/systemd/system/nvidia-persistenced.service
chmod +x nvidia-persistenced-init/install.sh
./nvidia-persistenced-init/install.sh
systemctl status nvidia-persistenced.service
rm -rf nvidia-persistenced-init*
nvidia-smi
, можно увидеть информацию про видеокарту.
root@pve1:~# nvidia-smi
Sat Mar 9 12:59:57 2024
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14 Driver Version: 550.54.14 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce GTX 1050 Ti On | 00000000:03:00.0 Off | N/A |
| 0% 35C P8 N/A / 75W | 4MiB / 4096MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
root@pve1:~# systemctl status nvidia-persistenced.service
● nvidia-persistenced.service - NVIDIA Persistence Daemon
Loaded: loaded (/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2024-03-09 00:38:15 +05; 12h ago
Process: 1543 ExecStart=/usr/bin/nvidia-persistenced --user nvidia-persistenced (code=exited, status=0/SUCCESS)
Main PID: 1546 (nvidia-persiste)
Tasks: 1 (limit: 76887)
Memory: 944.0K
CPU: 328ms
CGroup: /system.slice/nvidia-persistenced.service
└─1546 /usr/bin/nvidia-persistenced --user nvidia-persistenced
Mar 09 00:38:14 ekb-pve1 systemd[1]: Starting NVIDIA Persistence Daemon...
Mar 09 00:38:14 ekb-pve1 nvidia-persistenced[1546]: Started (1546)
Mar 09 00:38:15 ekb-pve1 systemd[1]: Started NVIDIA Persistence Daemon.
/dev/
root@pve1:~# ls -alh /dev/nvidia*
crw-rw-rw- 1 root root 195, 0 Mar 9 00:38 /dev/nvidia0
crw-rw-rw- 1 root root 195, 255 Mar 9 00:38 /dev/nvidiactl
crw-rw-rw- 1 root root 195, 254 Mar 9 00:38 /dev/nvidia-modeset
crw-rw-rw- 1 root root 511, 0 Mar 9 00:38 /dev/nvidia-uvm
crw-rw-rw- 1 root root 511, 1 Mar 9 00:38 /dev/nvidia-uvm-tools
/dev/nvidia-caps:
total 0
drwxr-xr-x 2 root root 80 Mar 9 00:38 .
drwxr-xr-x 21 root root 5.0K Mar 9 03:03 ..
cr-------- 1 root root 236, 1 Mar 9 00:38 nvidia-cap1
cr--r--r-- 1 root root 236, 2 Mar 9 00:38 nvidia-cap2
/dev/nvidia*
.
LXC-контейнер
Теперь, нужно добавить конфигурацию в LXC-контейнер. Останаливаем работу контейнера и вносим изменения в файле конфигурации LXC.
Отредактируем /etc/pve/lxc/101.conf
и добавим:
lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 237:* rwm
lxc.cgroup2.devices.allow: c 240:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-modeset dev/nvidia-modeset none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-caps/nvidia-cap1 dev/nvidia-caps/nvidia-cap1 none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-caps/nvidia-cap2 dev/nvidia-caps/nvidia-cap2 none bind,optional,create=file
cgroup2
взяты из 5 столбца в списках устройств выше (команда ls -alh /dev/nvidia*
)
После запускаем контейнер и приступаем к установке драйева Nvidia. Будем ставить без драйеверов ядра.
dpkg --add-architecture i386
apt update
apt install libc6:i386
wget -O NVIDIA-Linux-x86_64-550.54.14.run https://ru.download.nvidia.com/XFree86/Linux-x86_64/550.54.14/NVIDIA-Linux-x86_64-550.54.14.run
chmod +x NVIDIA-Linux-x86_64-550.54.14.run
./NVIDIA-Linux-x86_64-550.54.14.run --check
./NVIDIA-Linux-x86_64-550.54.14.run --no-kernel-module
После, выполняем reboot контейнеру LXC. Проверим, что все работает используя ls -alh /dev/nvidia*
и nvidia-smi
. Вывод будет таким же, как и для хоста.
Docker контейнер
Буду считать, что Plex уже работает, но транскодинг выполняется на процессоре.
Нужно установить NVIDIA Container Toolkit:
apt install -y curl
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt update
apt install nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
systemctl daemon-reload
systemctl restart docker
user@media:~$ docker run --rm --gpus all nvidia/cuda:11.0.3-base nvidia-smi
Sat Mar 9 08:17:54 2024
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14 Driver Version: 550.54.14 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce GTX 1050 Ti Off | 00000000:03:00.0 Off | N/A |
| 0% 35C P8 N/A / 75W | 4MiB / 4096MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
Plex + GPU
Нужно внести допстрочки в файл docker-compose, чтобы Plex начал видеть нашу видеокарту. Я приведу полный пример, как в итоге должен выглядеть файл.
version: "3.7"
services:
plex:
container_name: plex
image: linuxserver/plex:latest
profiles:
- plex
restart: unless-stopped
runtime: nvidia # закоментить, если образ plexinc/pms-docker
# Использование строк ниже, если образ plexinc/pms-docker
#deploy:
# resources:
# reservations:
# devices:
# - capabilities: [gpu]
ports:
- "32400:32400"
- "32400:32400/udp"
security_opt:
- no-new-privileges:true
volumes:
- ./plex:/config
- ./plex/temp:/transcode
- /mnt:/mnt:ro
environment:
- ADVERTISE_IP="http://172.18.1.250:32400/"
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- VERSION=docker
- PLEX_CLAIM=$PLEX_CLAIM
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,video,utility
Проверить что все работает, можно зайдя на свой сервер Plex и запустить какой нить фильм. В статистике, будет что то типо такого:
Обновление
Каждый раз, когда обновляется ядро, нужно переустановить драйвер на хосте Proxmox. При установке той же версии, что и стояла изначально, процесс прост: перезапустить исходную установку драйвера. В контейнере LXC ничего делать не нужно, так как версия остается той же)
./NVIDIA-Linux-x86_64-550.54.14.run
reboot
Обновление драйвера
При обновлении драйвера Nvidia, нужно выполнеить несколько дополнительных шагов. Если на хосте Proxmox уже есть работающий драйвер, то нужно для анчала удалить старый драйвер (иначе будут проблемы: при выгрузке модуля, будет происходить моментальная его загрузка обратно)
Удалим старый драйвер
./NVIDIA-Linux-x86_64-510.47.03.run --uninstall
reboot
pve-headers-$(uname -r)
apt install proxmox-headers-$(uname -r)
wget -O NVIDIA-Linux-x86_64-550.54.14.run https://ru.download.nvidia.com/XFree86/Linux-x86_64/550.54.14/NVIDIA-Linux-x86_64-550.54.14.run
chmod +x NVIDIA-Linux-x86_64-550.54.14.run
./NVIDIA-Linux-x86_64-550.54.14.run --check
./NVIDIA-Linux-x86_64-550.54.14.run
reboot
Tip
При установке, будет выбор что ставить дополнительно. В пунктах, перечисленных ниже, нужно ответить No
- install 32bit compability drivers
- should update X config
После перезагрузки, проверим что все работает, используя nvidia-smi
Проверим, что номера cgroup не изменились. если нужно, то меняем их под новые значения в файле конфигурации LXC
Далее, обновляем драйвера в контейнере LXC
wget -O NVIDIA-Linux-x86_64-550.54.14.run https://ru.download.nvidia.com/XFree86/Linux-x86_64/550.54.14/NVIDIA-Linux-x86_64-550.54.14.run
chmod +x NVIDIA-Linux-x86_64-550.54.14.run
./NVIDIA-Linux-x86_64-550.54.14.run --check
./NVIDIA-Linux-x86_64-550.54.14.run --no-kernel-module
После, выполняем reboot контейнеру LXC. Проверим, что все работает используя ls -alh /dev/nvidia*
и nvidia-smi
. Вывод будет таким же, как и для хоста.
Обновим NVIDIA Container Toolkit:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt update
apt install nvidia-container-toolkit
apt upgrade