Introduction
Les plugins de périphériques Kubernetes étendent le planificateur et le kubelet pour gérer le matériel spécialisé tel que les GPU, les FPGA ou les cartes réseau haute performance. Ces composants publient les ressources, gèrent l'allocation et attachent les périphériques aux conteneurs. Lorsqu'ils sont sous-performants, ils peuvent retarder le démarrage des pods, provoquer des échecs de planification et gaspiller des accélérateurs coûteux.
Ce guide fournit une approche pratique pour optimiser les performances des plugins de périphériques. Vous apprendrez à inventorier votre cluster, à mettre en œuvre des changements de configuration sûrs, à vérifier l'impact avec des commandes concrètes, à récupérer après des défaillances courantes et à maintenir une liste de contrôle opérationnelle reproductible. Un processus d'optimisation clair réduit les retouches en séparant la recherche, le cahier des charges, la mise en œuvre, la vérification et le déploiement.
Pour les performances des plugins de périphériques Kubernetes, un premier pilote utile doit être étroit, mesurable et facile à inspecter localement avant le déploiement. Nous nous concentrerons sur un exemple fictif de plugin GPU NVIDIA, mais les techniques s'appliquent à tout plugin qui suit l'API des plugins de périphériques Kubernetes.
Inventaire de la version et de l'environnement
Avant d'ajuster un paramètre, établissez une base de référence. Rassemblez les versions, la topologie des nœuds et le comportement actuel du plugin de périphériques. Cette section utilise des commandes kubectl et des extraits de configuration pour créer un point de référence fiable.
Informations sur le cluster et les nœuds
Identifiez la version de Kubernetes et les nœuds qui possèdent le matériel spécialisé.
kubectl version --short
kubectl get nodes -l accelerator=nvidia-gpu -o wide
Cette sortie affiche les versions du plan de contrôle Kubernetes et du kubelet, ainsi que les noms et les statuts des nœuds. Par exemple :
Client Version: v1.27.3
Server Version: v1.27.3
NAME STATUS ROLES AGE VERSION INTERNAL-IP
node-a1 Ready <none> 45d v1.27.3 10.0.0.11
node-a2 Ready <none> 45d v1.27.3 10.0.0.12
Vérifiez la configuration du kubelet sur chaque nœud pour voir les plugins de périphériques enregistrés et leurs chemins de socket.
sudo systemctl status kubelet --no-pager | grep -i device
ls -la /var/lib/kubelet/device-plugins/
Par exemple, vous pourriez voir nvidia-gpu.sock et kubelet_internal_checkpoint dans le répertoire des plugins de périphériques.
Détails du plugin de périphériques
Listez les pods du plugin de périphériques et leurs noms de ressources.
kubectl get pods -n kube-system -l app=nvidia-device-plugin -o wide
kubectl describe node node-a1 | grep -A10 "Capacity:\|Allocatable:"
La description du nœud montre les ressources personnalisées comme nvidia.com/gpu: 2. Les journaux du pod du plugin fournissent un aperçu de l'activité d'allocation.
kubectl logs -n kube-system nvidia-device-plugin-xxxxx --tail=50
Prérequis pour l'optimisation
Vous avez besoin d'un accès administrateur du cluster et de la permission de modifier les daemonsets ou les configmaps dans l'espace de noms kube-system. Vous avez également besoin de kubectl et, éventuellement, de jq pour analyser la sortie JSON.
kubectl auth can-i update daemonsets -n kube-system
kubectl auth can-i create configmaps -n kube-system
Les deux doivent renvoyer yes. Sinon, demandez un accès temporaire pour la fenêtre d'optimisation.
Chemin de configuration sûr
L'optimisation des plugins de périphériques implique souvent l'ajustement des paramètres d'enregistrement du kubelet, de l'allocation des ressources du plugin ou des règles de fonctionnalités des nœuds. Nous nous concentrerons sur deux domaines courants : les options d'enregistrement des plugins de périphériques du kubelet et les variables d'environnement ou arguments spécifiques au plugin.
Configuration des plugins de périphériques du kubelet
Le kubelet a des drapeaux qui influencent le comportement des plugins de périphériques. Le principal est --device-plugins-enabled, mais la plupart des optimisations se font dans la configuration propre du plugin. Cependant, vous pouvez modifier le délai d'enregistrement du kubelet ou le chemin vers le répertoire des plugins de périphériques.
Sur chaque nœud, modifiez le fichier de service systemd du kubelet (généralement /etc/systemd/system/kubelet.service.d/10-kubeadm.conf). Ajoutez le drapeau suivant pour augmenter le délai d'enregistrement pour les périphériques lents à démarrer :
Environment="KUBELET_EXTRA_ARGS=--device-plugin-registration-timeout=60s"
Cela donne au plugin plus de temps pour s'enregistrer avant que le kubelet ne le marque comme défaillant. Après avoir modifié, redémarrez le kubelet :
sudo systemctl daemon-reload
sudo systemctl restart kubelet
Configuration du plugin via ConfigMap
De nombreux plugins acceptent un fichier de configuration. Pour le plugin de périphériques NVIDIA, vous pouvez créer une ConfigMap pour changer la stratégie de liste des périphériques (device-list-strategy) ou définir fail-on-init-error. Voici un exemple de ConfigMap :
apiVersion: v1
kind: ConfigMap
metadata:
name: nvidia-device-plugin-config
namespace: kube-system
data:
config.yaml: |
version: v1
flags:
failOnInitError: false
deviceListStrategy: envvar
nvidiaDriverRoot: "/"
Ensuite, référencez la ConfigMap dans le DaemonSet du plugin de périphériques. Mettez à jour le DaemonSet avec un patch :
kubectl patch daemonset nvidia-device-plugin -n kube-system --type='json' -p='[
{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--config-file=/etc/nvidia-device-plugin/config.yaml"},
{"op": "add", "path": "/spec/template/spec/volumes/-", "value": {"name": "config", "configMap": {"name": "nvidia-device-plugin-config"}}},
{"op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/-", "value": {"name": "config", "mountPath": "/etc/nvidia-device-plugin"}}
]'
Après application, les pods du plugin redémarrent avec la nouvelle configuration.
Règles de fonctionnalités des nœuds et gestionnaire de topologie
Pour les charges de travail sensibles aux performances, alignez l'allocation des périphériques avec la topologie CPU et NUMA. Le gestionnaire de topologie coordonne l'affectation des ressources. Vous pouvez configurer le kubelet pour utiliser une politique spécifique (par exemple, single-numa-node) pour garantir que les périphériques sont sur le même nœud NUMA que les CPU.
Modifiez le fichier de configuration du kubelet (/var/lib/kubelet/config.yaml) pour activer le gestionnaire de topologie :
topologyManagerPolicy: single-numa-node
Redémarrez le kubelet. Ensuite, planifiez un pod avec une QoS garantie et des demandes de périphériques entiers ; le gestionnaire de topologie tentera de placer toutes les ressources sur le même nœud NUMA.
Dimensionnement des ressources et limites
L'optimisation ne concerne pas seulement l'allocation des périphériques ; les limites de ressources affectent la façon dont les charges de travail utilisent les périphériques. Assurez-vous que les pods qui utilisent des périphériques définissent des demandes et des limites CPU et mémoire appropriées pour éviter l'étranglement. Pour un pod GPU, une configuration typique pourrait être :
resources:
requests:
nvidia.com/gpu: 1
cpu: "2"
memory: "8Gi"
limits:
nvidia.com/gpu: 1
cpu: "4"
memory: "16Gi"
Utilisez kubectl apply pour mettre à jour le déploiement. Surveillez l'utilisation réelle avec kubectl top pods.
Vérification et diagnostics
Après les changements de configuration, vérifiez que le plugin de périphériques fonctionne comme prévu. Cette section fournit des commandes pour vérifier l'enregistrement, l'allocation et la latence, avec des exemples de sorties.
Contrôle de l'enregistrement du plugin de périphériques
Confirmez que le socket du plugin existe et que le kubelet le voit.
ls -l /var/lib/kubelet/device-plugins/
kubectl get --raw "/api/v1/nodes/node-a1/proxy/stats/summary" | jq '.pods[].device'
Le fichier socket indique que le plugin fonctionne. L'API stats peut montrer des métriques de périphériques si le plugin les expose.
Vérification de l'allocation des ressources
Créez un pod de test demandant un périphérique et observez qu'il démarre et obtient la ressource.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
containers:
- name: cuda-vector-add
image: k8s.gcr.io/cuda-vector-add: v0.1
resources:
limits:
nvidia.com/gpu: 1
EOF
kubectl get pod gpu-test
Le pod doit être dans l'état Running. Vérifiez les journaux pour voir si le GPU a été utilisé :
kubectl logs gpu-test
Pour l'exemple d'ajout de vecteur CUDA, la sortie se termine par quelque chose comme :
Test PASSED
Si le pod reste bloqué dans Pending, inspectez les événements :
kubectl describe pod gpu-test | grep -A5 Events
Recherchez les messages concernant des ressources insuffisantes ou un plugin de périphériques non prêt.
Contrôles de latence et de débit
Mesurez le temps entre la soumission du pod et l'allocation du périphérique.
time kubectl run -it --rm gpu-latency-test --image=busybox --restart=Never --limits=nvidia.com/gpu=1 -- sh -c 'echo GPU allocated'
Enregistrez le temps écoulé. Comparez avant et après l'optimisation. Pour un chronométrage plus détaillé, utilisez les événements Kubernetes :
kubectl get events --sort-by='.lastTimestamp' | grep -i "gpu-latency-test"
Les performances du plugin de périphériques lui-même peuvent être observées via ses journaux. Activez temporairement la journalisation verbeuse en ajoutant une variable d'environnement ou un drapeau (par exemple, -v=5). Vérifiez la capacité du plugin à gérer des taux d'allocation élevés en créant plusieurs pods simultanément :
for i in $(seq 1 10); do kubectl run gpu-$i --image=busybox --restart=Never --limits=nvidia.com/gpu=1 -- sleep 300 & done
Attendez quelques secondes et voyez à quelle vitesse ils deviennent tous prêts.
Surveillance avec Prometheus
Si vous avez Prometheus, interrogez des métriques telles que kubelet_device_plugin_allocatable_devices et kubelet_device_plugin_registration_total pour suivre la santé et l'enregistrement du plugin.
Exemple PromQL :
increase(kubelet_device_plugin_registration_total[5m])
Un nombre d'enregistrements stable indique l'absence de battement ; un taux élevé peut indiquer des redémarrages.
Modes de défaillance et récupération
Les changements d'optimisation peuvent introduire des défaillances. Cette section couvre les problèmes courants, comment les détecter et les étapes de récupération.
Échec de l'enregistrement du plugin de périphériques
Le plugin peut ne pas s'enregistrer si le socket est dans un mauvais état ou si le délai d'enregistrement du kubelet est trop court. Symptômes : les pods restent en Pending sans allocation de ressources, et les journaux du kubelet montrent des erreurs comme :
Failed to start device plugin ... context deadline exceeded
Récupération :
- Vérifiez le statut du pod du plugin :
kubectl get pods -n kube-system | grep device-plugin. - Redémarrez le pod du plugin :
kubectl delete pod -n kube-system <plugin-pod>. - Si l'enregistrement expire, augmentez
--device-plugin-registration-timeoutcomme décrit ci-dessus. - Si le plugin échoue constamment, revenez à la configuration précédente.
Surallocation des ressources du nœud
Si vous définissez trop de périphériques sur un nœud (par exemple, en configurant mal le plugin pour publier plus que physiquement disponible), le planificateur peut surallouer et les pods échoueront à l'exécution. Détectez avec :
kubectl describe node node-a1 | grep -A5 "Allocated resources"
Si vous voyez des demandes nvidia.com/gpu dépassant la capacité, corrigez la configuration du plugin. Un redémarrage progressif du plugin réannoncera le bon nombre.
Conflits du gestionnaire de topologie
L'activation de single-numa-node peut entraîner le rejet de pods si le périphérique et le CPU sont sur des nœuds NUMA différents. L'événement du pod montrera :
Topology Affinity Error
Récupération : soit assouplir la politique en best-effort ou none, soit planifier le pod avec des sélecteurs de nœuds explicites qui correspondent à la configuration NUMA. Revenez sur la politique du gestionnaire de topologie si le changement provoque des échecs de planification généralisés.
CrashLoopBackOff du plugin
Si le pod du plugin plante continuellement, vérifiez les journaux pour les erreurs de configuration.
kubectl logs -n kube-system <plugin-pod> --previous
Les erreurs courantes incluent un YAML mal formé ou des fichiers manquants. Corrigez la ConfigMap et laissez le DaemonSet se déployer. Si le problème persiste, revenez à la version précédente du DaemonSet :
kubectl rollout undo daemonset nvidia-device-plugin -n kube-system
Dégradation des performances
Si la latence augmente après l'optimisation, revenez sur le changement pertinent. Par exemple, si vous avez changé deviceListStrategy de envvar à volume-mounts et observez une allocation plus lente, revenez à envvar. Utilisez kubectl describe pour inspecter la ConfigMap actuelle et la comparer avec la version précédente.
Maintenez toujours un plan de retour en arrière : conservez la ConfigMap ou le manifeste du DaemonSet précédent dans le contrôle de version, et testez les procédures de retour en arrière dans un environnement de préproduction avant la production.
Pièges courants
Évitez ces erreurs fréquentes lors de l'optimisation des plugins de périphériques :
- Ignorer les métriques de base : Sans comparaison avant/après, vous ne pouvez pas savoir si un changement a aidé ou nui. Enregistrez toujours la latence d'allocation et l'état d'enregistrement avant de modifier quoi que ce soit.
- Modifier plusieurs paramètres à la fois : Si vous modifiez le délai d'enregistrement et la stratégie de liste des périphériques simultanément, il est impossible d'attribuer une amélioration ou une régression. Changez une variable à la fois.
- Ne pas vérifier la localité des nœuds : Pour les charges de travail sensibles à NUMA, ne pas configurer le gestionnaire de topologie peut entraîner un trafic inter-NUMA et une dégradation des performances. Testez avec
numactl --hardwaresur le nœud pour comprendre la topologie. - Surallouer les périphériques : Mal configurer le plugin pour publier plus de périphériques que disponibles conduit à une surallocation et à des échecs de pods. Vérifiez toujours le nombre physique de périphériques avec
nvidia-smiou équivalent avant d'ajuster les drapeaux du plugin. - Oublier de surveiller la santé du plugin : Un plugin peut sembler enregistré mais échouer pendant l'allocation. Utilisez des alertes Prometheus pour les comptes d'enregistrement et les erreurs d'allocation.
- Ne pas avoir de plan de retour en arrière : Gardez toujours les manifestes précédents dans le contrôle de version et pratiquez le retour en arrière dans un environnement hors production.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour chaque cycle d'optimisation afin d'assurer la cohérence et d'éviter les erreurs. Chaque élément comprend un propriétaire responsable et une fréquence de révision.
| Étape | Action | Commande/Vérification | Propriétaire | Fréquence de révision |
|---|---|---|---|---|
| 1 | Enregistrer les versions et la topologie de base | kubectl version --short, kubectl get nodes -o wide | Ingénieur plateforme | Chaque cycle d'optimisation |
| 2 | Vérifier l'enregistrement du plugin de périphériques | ls -l /var/lib/kubelet/device-plugins/ | Administrateur système | Chaque cycle d'optimisation |
| 3 | Créer un pod de test avec demande de périphérique | kubectl apply -f test-pod.yaml, kubectl get pod | Ingénieur QA | Chaque cycle d'optimisation |
| 4 | Mesurer la latence d'allocation | time kubectl run ... --limits=nvidia.com/gpu=1 | Ingénieur performance | Chaque cycle d'optimisation |
| 5 | Appliquer le changement de configuration à un nœud ou à un groupe canari | Patcher le DaemonSet avec kubectl patch | Ingénieur plateforme | Chaque changement |
| 6 | Observer les journaux du plugin pour les erreurs | kubectl logs -n kube-system <plugin-pod> | Administrateur système | Immédiatement après le changement |
| 7 | Réexécuter le pod de test et mesurer à nouveau la latence | Identique à l'étape 4 | Ingénieur performance | Après le changement |
| 8 | Surveiller les demandes de ressources par rapport à la capacité | kubectl describe node node-a1 | grep -A5 "Allocated resources" | Administrateur système | Hebdomadaire |
| 9 | Revenir en arrière si la métrique se dégrade ou si des défaillances surviennent | kubectl rollout undo daemonset | Ingénieur plateforme | Selon besoin |
| 10 | Documenter le changement et les résultats dans un runbook | - | Responsable technique | Après chaque cycle d'optimisation |
Conclusion
L'optimisation des plugins de périphériques Kubernetes nécessite un inventaire minutieux, des changements incrémentaux et une vérification approfondie. En vous concentrant sur un pilote étroit et mesurable, vous pouvez optimiser les performances en toute sécurité sans perturber les opérations du cluster.
Points clés à retenir :
- Commencez par une base solide : versions, nombre de nœuds, configuration du plugin et latence d'allocation.
- Changez un paramètre à la fois, de préférence sur un nœud canari.
- Utilisez des commandes concrètes et des sorties attendues pour vérifier chaque étape.
- Ayez toujours un plan de retour en arrière et testez-le avant d'apporter des changements en production.
- Intégrez la liste de contrôle opérationnelle dans votre routine de maintenance régulière.
Avec ce guide, vous pouvez systématiquement améliorer les performances des plugins de périphériques, réduire la latence de démarrage des pods et assurer une allocation fiable du matériel spécialisé dans vos clusters Kubernetes.