Utiliser des GPUs avec Kubernetes

Watch the webinar

Ce post décrit l’utilisation de GPUs avec Kubernetes et DevicePlugins.

Nous allons utiliser MicroK8s pour une station de développement et Charmed K8s pour un cluster. Ceci est consistant avec une approche multi-cloud. Les différents CAAS disponibles sur les clouds public comme GKE ont aussi une option GPU, vous pouvez aussi essayer cela.

Nous allons utiliser Ubuntu comme OS simplement parce que GPU fonctionne bien sur tous les clouds en version Ubuntu et avec tout le hardware local. Et faire les images Docker sur Ubuntu garantit que les librairies CUDA soient alignées avec les drivers.

Pour que tout cela fonctionne, le bon driver a besoin d’être installé sur le worker node pour que le GPU soit accessible à partir de l’OS; et typiquement, cela demande aussi des librairies userland pour fonctionner.

Avec NVIDIA GPUs, cette activation dépend en plus de la bonne utilisation de Docker runtime (nvisia-docker2) qui demande des configurations supplémentaires au niveau du host et une installation après déploiement.

Tout cela est automatisé sur Ubuntu avec MicroK8s et les charms Charmed Kubernetes, sur tous les clouds publics où les GPUs sont disponibles. Ceci est aussi disponible pour GKE et les autres offres CAAS vont suivre.

Des conteneurs GPU sur workstation avec Microk8s

MicroK8s est un snap Kubernetes upstream conçu pour le développement. Ce n’est pas un cluster mais un environnement Kubernetes sans besoin d’opération qui est compatible avec les offres Kubernetes multi-cloud. Pour arriver à nos fins il faut que l’option GPU soient actives dès la sortie de l’emballage.

Pour installer MicroK8s:

$ snap install microk8s --classic

Cela vous donne la dernière version stable de MicroK8s qui trace de très près les sorties upstream.

Vous pouvez sélectionner une version particulière en utilisation l’option ‘snap channels’, regarder ‘snap info microk8s’ pour voir les différentes versions.

En sélectionnant une version particulière, vous pouvez rester bloqué sur cette version.

Par défaut, vous êtes sur la dernière version et vous avez les upgrades quand Kubernetes upstream sortira une nouvelle version stable.

Sélectionner une version particulière avec l’option: --channel=track/stability grâce aux différentes chaînes disponibles. “Stable” vous amène à “latest/stable”.

$ snap info microk8s
[...]
channels:
  stable: v1.13.0 (340) 204MB classic 
  candidate: v1.13.0 (340) 204MB classic
  beta: v1.13.0 (340) 204MB classic 
  edge: v1.13.0 (340) 204MB classic
  1.13/stable: v1.13.0 (340) 204MB classic 
  1.13/candidate: v1.13.0 (340) 204MB classic
  1.13/beta: v1.13.0 (340) 204MB classic
  1.13/edge: v1.13.0 (341) 204MB classic
  1.12/stable: v1.12.3 (336) 226MB classic
  1.12/candidate: v1.12.3 (336) 226MB classic
  1.12/beta: v1.12.3 (336) 226MB classic
  1.12/edge: v1.12.3 (336) 226MB classic 
  1.11/stable: v1.11.5 (322) 219MB classic
  1.11/candidate: v1.11.5 (322) 219MB classic
  1.11/beta: v1.11.5 (322) 219MB classic
  1.11/edge: v1.11.5 (322) 219MB classic
  1.10/stable: v1.10.11 (321) 175MB classic 
  1.10/candidate: v1.10.11 (321) 175MB classic
  1.10/beta: v1.10.11 (321) 175MB classic
  1.10/edge: v1.10.11 (321) 175MB classic 

Supposons que vous avez un GPU Nvidia avec le bon driver installé, vous pouvez activer le support Kubernetes avec la sous command “enable”.

$ microk8s.enable gpu

Vous pouvez confirmer que le GPU est disponible avec la commande suivante:

$ microk8s.status
microk8s is running
addons:
gpu: enabled
storage: disabled
registry: disabled
ingress: disabled
dns: disabled
metrics-server: disabled
istio: disabled
dashboard: disabled

Faire tourner des conteneurs GPU accélérés sur K8s

Maintenant que vous avez de la capacité GPU disponible pour votre Kubernetes, vous pouvez déployer des containers qui ont accès au hardware dont ils ont besoin.

Vos containers ont besoin des bonnes pièces userspaces, donc nous vous suggérons de construire les images OCI sur Ubuntu avec les librairies CUDA fournies; ces derniers seront portables sur toutes les offres CAAS cloud ainsi que les offres de Canonical, VMware, Pivotal, Cisco et autres qui utilise Ubuntu pour K8s.

Vos workloads peuvent maintenant utiliser quelque chose comme cela pour sélectionner le bon worker node. (exemple extrait d’ici):

Listing 1: nvidia-pod-example.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cuda-vector-add
spec: 
  restartPolicy: OnFailure
  containers:
  - name: cuda-vector-add
    image: "k8s.gcr.io/cuda-vector-add:v0.1"
    resources:
      limits: nvidia.com/gpu: 1 # requesting 1 GPU

Déploiement d’un cluster Kubernetes avec GPUs

Une caractéristique intéressante de Charmed Distribution of Kubernetes (CDK) est qu’il active automatique les ressources GPU qui sont présentent sur le worker node pour être utilisées par les pods.

Les ressources GPU sont activé par l’usage de Device Plugins qui sont
déployés comme DaemonSets. Cela assure que chaque worker node avec activation GPU puisse accéder au GPU et mette en place le bon chemin vers les drivers plugins du host. Avec DaemonSet déployé, le planificateur Kubernetes peut prendre avantage du NodeSelector pour filtrer les worker nodes qui proposent la fonction nvidia.com/gpu quand il planifie les workloads.

Les Charms automatisent complètement le déploiement de Kubernetes d’une façon qui est orientée modèle et sont donc flexibles pour être utilisés sur différents types de clouds ou clusters. Nous utilisons les Charms pour les déploiements HPC de Kubernetes, par exemple, déployer des pipelines AI/ML au dessus de Kubernetes de manière plus facile. L’activation du GPU est important pour ce genre de workload.

Cependant, avant de déployer Kubeflow ou d’autres frameworks, la couche Kubernetes doit être complètement automatisée et les GPUs actives.

Les Charms de K8s font tout le travail. Au fur et à mesure que les worker nodes sont commissionnés dans le modèle, les Charms de K8s détectent automatiquement la présence des cartes nvidia, installent les bons drivers et les bonnes librairies, remplacent le runtime du container par celui qui est supporté par NVIDIA, déploient le DaemonSet pour le DevicePlugin et catégorisent les nodes automatiquement.

Le cluster K8s est facilement déployé avec conjure-up qui fournit un wizard pour vous accompagner tout le long du processus. Vous pouvez utiliser conjure-up sur un cloud public avec des instances GPUs activées, ou avec MAAS pour des clusters sur bare metal avec des serveurs qui contiennent des GPUs. Dans les deux cas, le déploiement est exactement le même.

Par exemple, vous pouvez utiliser des instances p2.xlarge sur AWS. Pour que cela fonctionne, vous devez passer la contrainte dans le command line de conjure-up pour qu’il force l’usage d’instances avec des GPUs actives quand on déploie les clusters.

Listing 2: cdk-gpu-worker.yaml

services:
"kubernetes-worker":
  charm: "cs:~containers/kubernetes-worker" 
  num_units: 1
  options:
    channel: 1.13/stable
  expose: true
  constraints: "instance-type=p2.xlarge root-disk=32768"

Mettre ceci dans conjure-up:

$ conjure-up canonical-kubernetes --bundle-add cdk-gpu-worker.yaml

Cela démarrera l‘interface wizard de conjure-up et vous permettra de sélectionner les add-ons à déployer, par exemple, Kubeflow peut être sélectionné ici.

À l’écran de sélection du controller, vous pouvez soit déployer un contrôleur Juju dédié (nécessite une VM) ou vous pouvez prendre avantage de JAAS qui fournit Juju As a Service sur tous les clouds publics majeurs.

Une fois que l’installation commence, vous avez cet écran:

Le statut peut aussi être visualisé en utilisant la commande Juju
directement. Si vous utilisez JAAS, vous pouvez trouver le model en tapant:

$ juju models -c jaas
Controller: jaas
Model                         Cloud/Region   Status     Machines  Cores  Access  Last   connection
conjure-canonical-kubern-9dc  aws/us-east-1  available         0      0  admin   never   connected

Inspectez alors le statut du model:

$ juju status -m jaas:conjure-canonical-kubern-9dc
Model                         Controller  Cloud/Region   Version  SLA          Timestamp
conjure-canonical-kubern-9dc  jaas        aws/us-east-1  2.4.5    unsupported  16:13:37-08:00

App                    Version  Status       Scale  Charm                  Store       Rev  OS      Notes
aws-integrator         1.15.71  active           1  aws-integrator         jujucharms    7  ubuntu
easyrsa                3.0.1    maintenance      1  easyrsa                jujucharms  117  ubuntu
etcd                            maintenance      3  etcd                   jujucharms  209  ubuntu
flannel                         waiting          0  flannel                jujucharms  146  ubuntu 
kubeapi-load-balancer           maintenance      1  kubeapi-load-balancer  jujucharms  162  ubuntu  exposed
kubernetes-master               maintenance      2  kubernetes-master      jujucharms  219  ubuntu
kubernetes-worker               waiting        0/1  kubernetes-worker      jujucharms  239  ubuntu  exposed

Unit                      Workload     Agent       Machine  Public address  Ports  Message
aws-integrator/0*         active       idle        0        54.165.35.94           ready
easyrsa/0*                maintenance  executing   1        34.234.207.232         (install) installing charm
etcd/0*                   maintenance  executing   2        54.208.163.252         (install) installing charm
etcd/1                    maintenance  executing   3        34.201.210.154         (install) installing charm
etcd/2                    maintenance  executing   4        54.235.228.45          (install) installing charm
kubeapi-load-balancer/0*  maintenance  executing   5        34.228.169.37          (install) installing charm
kubernetes-master/0       maintenance  executing   6        18.207.179.122         (install) installing charm
kubernetes-master/1*      maintenance  executing   7        18.212.150.203         (install) installing charm 
kubernetes-worker/0       waiting      allocating  8        35.175.104.2           waiting for machine 

Machine  State    DNS             Inst id              Series  AZ Message
0        started  54.165.35.94    i-083ce279733998d59  bionic  us-east-1a running
1        started  34.234.207.232  i-04828688ddfdb0c6c  bionic  us-east-1b running
2        started  54.208.163.252  i-03d910e892e7c09f6  bionic  us-east-1a running
3        started  34.201.210.154  i-00adeecd668174ee0  bionic  us-east-1b running
4        started  54.235.228.45   i-032875fd24a1c1e78  bionic  us-east-1c running
5        started  34.228.169.37   i-0008405049b9bed6d  bionic  us-east-1d running
6        started  18.207.179.122  i-003abf7f3612a2f18  bionic  us-east-1b running
7        started  18.212.150.203  i-0abe01060e8179618  bionic  us-east-1a running
8        pending  35.175.104.2    i-0d493a35776b9217d  bionic  us-east-1e running

Une fois l’installation finie, toutes les ressources GPU sont configurées correctement et disponibles pour l’opérateur K8s. Vous pouvez vérifier cela avec la commande:

$  ubectl get no -o wide -L cuda,gpu

Conclusion

Utiliser les ressources GPU dans votre cluster Kubernetes est automatique
et facile avec Charmed Distribution of Kubernetes (CDK) ou Microk8s.

Qu’en pensez vous? Nous serions ravis de discuter de votre projet et de la
façon dont CDK et/ou MicroK8s vous ont aidé avec vos workloads sensitifs
aux GPUs.

Nous contacter