diff --git a/docs/images/proxmox/proxmox-nvidia-1.png b/docs/images/proxmox/proxmox-nvidia-1.png new file mode 100644 index 0000000..61bd786 Binary files /dev/null and b/docs/images/proxmox/proxmox-nvidia-1.png differ diff --git a/docs/proxmox/nvidia-lxc.md b/docs/proxmox/nvidia-lxc.md new file mode 100644 index 0000000..c047cc2 --- /dev/null +++ b/docs/proxmox/nvidia-lxc.md @@ -0,0 +1,318 @@ +# 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. + +!!! info "Запуск в 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 +``` +Устанавливаем пакеты, необходимые для сборки драйверов ядра NVIDIA (нужны только на хосте) +``` +apt install build-essential +``` +Установливаем заголовки pve, соответствующие вашему текущему ядру. Для старых версий нужно использовать `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. Это необходимо для того, чтобы гарантировать загрузку правильных модулей ядра и создание всех соответствующих файлов устройств при загрузке. + +``` title="добавляем модули ядра" +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" +``` +Чтобы избежать выгрузки модуля драйвера/ядра всякий раз, когда графический процессор не используется, нужно запустить службу сохранения, предоставляемую Nvidia . Он становится доступен после установки драйвера. + +Копируем и извлекаем. +``` +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* +``` +Если до этого момента не было ошибок, то можно перезагрузить хост Proxmox. После перезагрузки, введя команду `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 +``` +Понять что все хорошо - есть минимум 5 файлов `/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 +``` +Монтирование устройств nvidia в контейнер LXC +``` +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 +``` +Как и для хоста, отказываем от обновления конфигурации X + +После, выполняем 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 + +systemctl daemon-reload +systemctl restart docker +``` +Проверить, что Docker работает с поддержкой GPU можно через контейнер: +``` +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 начал видеть нашу видеокарту. Я приведу полный пример, как в итоге должен выглядеть файл. + +```yaml hl_lines="10-14 29 30" +version: "3.7" + +services: + plex: + container_name: plex + image: linuxserver/plex:latest + profiles: + - plex + restart: unless-stopped + 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 и запустить какой нить фильм. В статистике, будет что то типо такого: + +![](../images/proxmox/proxmox-nvidia-1.png) + +## Обновление + +Каждый раз, когда обновляется ядро, нужно переустановить драйвер на хосте 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 +``` +Как и для хоста, отказываем от обновления конфигурации X + +После, выполняем 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 +``` +Перезагружаем контейнер LXC. Все должно рбаотать с новым драйвером. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index fd3f8c2..6b993a0 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -118,6 +118,7 @@ nav: - Proxmox VE: - proxmox/index.md - CT Template: proxmox/ct-template.md + - Nvidia LXC: proxmox/nvidia-lxc.md - Умный дом: - Home Assistant: - Установка на Debian: smart-home/hass/install-hass-debian.md