Podman et Nvidia, ou comment avoir accès à son GPU dans un conteneur

Il y a un moment que Docker peut utiliser votre carte Nvidia, et Podman n'est pas en reste. Cependant, il est important de connaître la méthode appropriée. Voici un guide détaillé pour la configuration de Podman avec Nvidia sur Fedora.
Partager sa carte graphique avec un conteneur est très intéressant. Cela évite d’une part d’avoir à installer localement toute une batterie de packages et de librairie (surtout pour CUDA qui est une plaie), de rendre jetable un test, de partager une application utilisant le Machine-Learning simplement, etc.
Bref, c’est utile et ça soulage.
Mais ce n’est pas évident à activer. La conteneurisation sert à isoler l’application du système, et là on veut absolument lui partager un périphérique. Et pas n’importe lequel, pas une imprimante USB ou une caméra… non… là on parle d’une carte graphique. Heureusement, les derniers efforts de Nvidia à proposer de la documentation et leur ouverture de certaines parties de leur travail permet de s’en sortir avec un peu plus de confort.
TL;DR
Pour les pressés, voici les étapes rapides :
# installer le dépot de nvidia container toolkit
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
# puis les outils
sudo dnf install nvidia-container-toolkit
# et on commence par créer le fichier de configuration
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
# on corrige les soucis SELinux
nvidia-container-cli -k list | sudo restorecon -v -f -
sudo restorecon -Rv /dev
Si vous voulez utiliser Podman en “rootless”, il faut modifier avec sudo, le fichier /etc/nvidia-container-runtime/config.toml
,
on trouve les deux lignes qui nous intéresse :
[nvidia-container-cli]
#no-cgroups = false
no-cgroups = true
[nvidia-container-runtime]
#debug = "/var/log/nvidia-container-runtime.log"
debug = "~/.local/nvidia-container-runtime.log"
Et on peut tester, il faut bien ajouter --device nvidia.com/gpu=all
et --security-opt=label=disable
.
podman run --rm \
--device nvidia.com/gpu=all \
--security-opt=label=disable \
ubuntu nvidia-smi -L
# ça doit vous donner un truc de ce genre:
GPU 0: NVIDIA GeForce RTX 3070 (UUID: GPU-f7187582-1105-9022-2d77-ac16ed3b10ca)
Voilà, c’est tout…
En détail…
Bon, on va expliquer pas à pas ce qu’il faut faire.
Installer les outils de Nvidia
Nvidia propose des outils assez bien foutus pour permettre à Docker et Podman (mais aussi à Kubernetes, etc…) de partager votre carte graphique avec des conteneurs OCI. Le fait est que depuis quelque temps, et ce grâce à l’explosion des travaux en Machine-Learning, Nvidia est aux avant-postes. Du coup, ils ont mis les bouchées doubles, ont ouvert une partie de leur code, et ils se sont mis à documenter correctement tout leur boxon.
Pour le coup, on peut souligner les efforts et leur dire merci.
Bref, la documentation est assez complète et les outils assez “simples” à utiliser.
Je suis sur Fedora, donc je ne vais pas tortiller pendant des heures avec Ubuntu. L’installation commence par ajouter le dépôt officiel pour Fedora:
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
Ce dépôt vous propose quelques outils, mais c’est nvidia-ctk
et nvidia-container-cli
qui nous intéressent. Et ces outils se trouvent dans le package nvidia-container-toolkit
:
sudo dnf install nvidia-container-toolkit
À partir de là, on est paré pour la suite.
Configurer pour Podman
La doc est assez claire, mais elle va vous vous guider, ensuite, vers une autre page pour Podman.
Nvidia vous demande d’utiliser plutôt “CDI” (Container Devide Interface) pour configurer l’accès à votre périphérique. Et cette page vous demande de faire deux trois bricoles.
La première commande va générer un fichier yaml
qui liste les “devices” et les “hooks” à effectuer quand le conteneur va demander l’accès à ces périphériques. Le faire à la main aurait été une plaie, là, c’est simple :
# enlevez --output=... pour voir ce qu'il va générer
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
Après cela, vous pouvez contrôler la liste des périphériques qu’il a configuré :
nvidia-ctk cdi list
# il doit vous sortir un truc du genre
# nvidia.com/gpu=all
# nvidia.com/gpu=0
Ces lignes, ce sont les options à --device
qu’on pourra donner à Podman. Vous allez voir ça juste après.
Si cette étape s’est bien passé, on va corriger les attributs SELinux au cas où… (en réalité je pense que ce n’est pas nécessaire, mais dans le doute…)
nvidia-container-cli -k list | sudo restorecon -v -f -
sudo restorecon -Rv /dev
Il reste un dernier point, et pas des moindres, c’est de corriger la manière dont on va permettre à Podman d’écrire des logs et d’utiliser les cgroups
et ce, seulement si vous voulez utiliser le mode “rootless” de Podman.
C’est tout de même l’un des points forts de Podman, dont on ne s’en privera pas. Je vous conseille donc de le faire !
Ouvrez, avec les droits d’admin (donc sudo vim
ou sudo nano
) le fichier /etc/nvidia-container-runtime/config.toml
pour toucher deux lignes:
- La première dans le groupe
nvidia-container-cli
pour lui dire de se passer descgroups
(ouais bah… bon…) - L’autre dans le groupe
nvidia-container-runtime
pour lui changer le chemin des logs car, de base, il va taper dans/var/log
et vous, en tant qu’utilisateur, vous ne pourrez pas le faire.
Donc en gros, trouvez les lignes (normalement commentées), copiez-les en dessous et changez la valeur. Surtout, gardez les autres lignes telles quelles :
[nvidia-container-cli]
#no-cgroups = false
no-cgroups = true
[nvidia-container-runtime]
#debug = "/var/log/nvidia-container-runtime.log"
debug = "~/.local/nvidia-container-runtime.log"
Pour référence, voici mon fichier à moi :
#accept-nvidia-visible-devices-as-volume-mounts = false
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
disable-require = false
supported-driver-capabilities = "compat32,compute,display,graphics,ngx,utility,video"
#swarm-resource = "DOCKER_RESOURCE_GPU"
[nvidia-container-cli]
#debug = "/var/log/nvidia-container-toolkit.log"
environment = []
#ldcache = "/etc/ld.so.cache"
ldconfig = "@/sbin/ldconfig"
load-kmods = true
#no-cgroups = false
no-cgroups = true
#path = "/usr/bin/nvidia-container-cli"
#root = "/run/nvidia/driver"
#user = "root:video"
[nvidia-container-runtime]
#debug = "/var/log/nvidia-container-runtime.log"
debug = "~/.local/nvidia-container-runtime.log"
log-level = "info"
mode = "auto"
runtimes = ["docker-runc", "runc"]
[nvidia-container-runtime.modes]
[nvidia-container-runtime.modes.cdi]
annotation-prefixes = ["cdi.k8s.io/"]
default-kind = "nvidia.com/gpu"
spec-dirs = ["/etc/cdi", "/var/run/cdi"]
[nvidia-container-runtime.modes.csv]
mount-spec-path = "/etc/nvidia-container-runtime/host-files-for-container.d"
[nvidia-container-runtime-hook]
path = "nvidia-container-runtime-hook"
skip-mode-detection = false
[nvidia-ctk]
path = "nvidia-ctk"
Attention, quand vous mettez à jour vos packages, ce fichier est écrasé. Ou pas… en fait il y aura un fichier
config.toml.rpmsave
dans lequel il y aura vos anciennes modifications. Mais je vous conseille d’utiliser le fichier mis à jour, qui généralement à des modifications importantes, et de simplement remettre d’aplomb les lignes qu’on a changées.
Voilà… on a fini. Reste à tester :
podman run --rm \
--device nvidia.com/gpu=all \
--security-opt=label=disable \
ubuntu nvidia-smi -L
# doit vous donner la même ligne que `nvidia-smi` en local
# pour ma part :
GPU 0: NVIDIA GeForce RTX 3060 Laptop GPU (UUID: GPU-21c9319b-4c2d-84db-f028-cd065f9d9e8f)
Important
Vous allez certainement tester des outils qui ne parlent que de Docker, alors que ça marche très bien avec Podman. La seule chose à penser c’est de ne pas utiliser le paramètre --gpus
(qui ne marche pas sur Podman et je ne sais pas pourquoi), mais d’utiliser --device nvidia.com/gpu=all
(ou l’index de carte à la place de all
, par exemple nvidia.com/gpu=0
) et de forcer la non-labellisation avec --security-opt=label=diable
.
Sans cela, vous allez vous prendre des erreurs dans la poire sans rien comprendre.
Pour ma part j’ai ajouté un alias dans mon environnement :
alias podman-gpu="podman run --device nvidia.com/gpu=all --security-opt=label=disable"
Et c’est beaucoup plus simple 😄
Conclusion
Ce n’est pas évident, je vous l’accorde. Mais ce n’est pas insurmontable en réalité. La seule chose à bien penser est de refaire la modification du fichier toml
pour les cgroups
et le chemin des logs quand les packages sont mis à jour.
C’est d’ailleurs dommage que nous ne pouvions pas utiliser un fichier d’override (c’est peut-être possible, si c’est le cas je modifierai l’article), mais bon… ça me prend moins d’une minute à faire tout ça.
L’intérêt est de pouvoir lancer des inférences, des entrainements, des outils utilisant le GPU sans installer tout ça localement. C’est aussi intéressant de pouvoir tester plusieurs versions de CUDA sans les installer à l’arrache.
Podman est devenu mon seul et unique runtime de conteneur depuis des mois, du moins sur mon poste Linux (car je suis forcé d’utiliser un poste Windows dans mon nouveau Job).