## Introduction L'affinité de nœud Kubernetes vous offre un contrôle précis sur l'ordonnancement des pods en déclarant des règles qui attirent les pods vers des nœuds spécifiques. Lorsque ces règles sont mal configurées ou mal comprises, les pods peuvent rester en état Pending , être expulsés de manière inattendue ou atterrir sur le mauvais matériel. Cet article passe en revue les erreurs d'affinité de nœud les plus courantes, comment les diagnostiquer avec des commandes concrètes et comment les corriger avec des exemples pratiques. Vous apprendrez à distinguer requiredDuringSchedulingIgnoredDuringExecution de preferredDuringSchedulingIgnoredDuringExecution , à lire les événements du planificateur avec kubectl describe pod , et à corriger les inadéquations d'étiquettes, les opérateurs invalides et les erreurs de clé de topologie. Chaque correctif inclut des extraits de manifeste à copier-coller et des étapes de vérification pour appliquer la solution en toute sécurité dans un espace de noms de développement avant de la déployer en production. ## Inventaire des versions et de l'environnement Avant de modifier un manifeste, confirmez la version de Kubernetes et les nœuds du cluster. La syntaxe de l'affinité de nœud est stable dans les versions récentes, mais le comportement des étiquettes et les messages du planificateur peuvent varier légèrement selon la version. Exécutez : kubectl version --short kubectl get nodes --show-labels La sortie attendue comprend une ligne de version du serveur comme Server Version: v1.28.2 et une liste de nœuds avec leurs étiquettes. Par exemple : NAME STATUS ROLES AGE VERSION LABELS node-1 Ready control-plane 10d v1.28.2 kubernetes.io/hostname=node-1,disktype=ssd,region=us-east node-2 Ready 10d v1.28.2 kubernetes.io/hostname=node-2,disktype=hdd,region=us-west Si votre cluster est géré (EKS, GKE, AKS), utilisez l'interface de ligne de commande du fournisseur de cloud pour vérifier la version du plan de contrôle, mais les étiquettes des nœuds restent visibles via kubectl . Notez les clés et valeurs d'étiquettes exactes que vous prévoyez d'utiliser dans votre règle d'affinité. Une erreur courante consiste à supposer qu'une étiquette existe alors qu'elle n'existe pas. Avant d'ajouter disktype: ssd à votre affinité, vérifiez qu'au moins un nœud possède effectivement cette étiquette : kubectl get nodes -l disktype=ssd Aucune sortie ne signifie qu'aucun nœud ne correspond, et toute règle requiredDuringSchedulingIgnoredDuringExecution utilisant cette étiquette ne planifiera jamais.
Question rapide 1 sur 2 Quelle est la principale différence entre requiredDuringSchedulingIgnoredDuringExecution et preferredDuringSchedulingIgnoredDuringExecution dans node affinity ? - Les règles obligatoires sont toujours appliquées, tandis que les règles préférées sont facultatives. - Les règles préférées sont appliquées, tandis que les règles obligatoires sont facultatives. - Les règles obligatoires ignorent les modifications de labels après la planification, tandis que les règles préférées ne le font pas. - Les règles préférées sont uniquement appliquées aux pods existants.
Selon la référence, requiredDuringSchedulingIgnoredDuringExecution signifie que le scheduler ne peut pas planifier le Pod à moins que la règle soit respectée, tandis que preferredDuringSchedulingIgnoredDuringExecution signifie que le scheduler essaie de trouver un nœud correspondant mais planifiera quand même le Pod si aucun n'est trouvé.
## Chemin de configuration sécurisé Testez toujours les modifications d'affinité dans un espace de noms hors production d'abord. Le plus petit test sûr est un pod unique avec une règle d'affinité simple qui reflète votre logique de production prévue. Par exemple : apiVersion: v1 kind: Pod metadata: name: affinity-test spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: disktype operator: In values: - ssd containers: - name: nginx image: nginx:1.25 Appliquez-le et vérifiez immédiatement l'état du pod : kubectl apply -f affinity-test.yaml kubectl get pod affinity-test -o wide Si le pod est planifié et s'exécute sur un nœud avec disktype=ssd , votre règle fonctionne. S'il est en Pending , exécutez kubectl describe pod affinity-test et consultez la section Events : Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 10s default-scheduler 0/2 nodes are available: 2 node(s) didn't match node selector. Ce message confirme que la règle d'affinité a exclu tous les nœuds. Corrigez l'étiquette ou la règle avant de continuer. ## Vérification et diagnostics Le diagnostic des échecs d'affinité de nœud nécessite d'examiner le processus de décision du planificateur. Commencez par les événements du pod, puis inspectez les étiquettes des nœuds et l'expression d'affinité elle-même. ### Étape 1 : Décrire le pod en attente kubectl describe pod Recherchez les événements FailedScheduling . Ils vous indiqueront pourquoi aucun nœud ne correspondait. Par exemple : 0/3 nodes are available: 1 node(s) had untolerated taint {dedicated: infrastructure}, 2 node(s) didn't match node affinity/selector. Cela sépare les problèmes de teinture des problèmes d'affinité. Si les teintures sont le problème, vous avez besoin de tolérances, pas de modifications d'affinité. Si l'affinité est le problème, passez à la vérification des étiquettes. ### Étape 2 : Vérifier les étiquettes des nœuds existants kubectl get nodes --show-labels | grep disktype Si aucune sortie, la clé d'étiquette n'existe sur aucun nœud. Ajoutez-la aux nœuds appropriés : kubectl label node node-1 disktype=ssd Puis vérifiez : kubectl get node node-1 --show-labels Sortie partielle attendue : ... disktype=ssd ### Étape 3 : Valider l'expression d'affinité Les erreurs courantes incluent : - Utiliser operator: Equal avec plusieurs valeurs (invalide ; Equal accepte exactement une valeur). - Utiliser operator: In mais laisser values vide. - Mal orthographier requiredDuringSchedulingIgnoredDuringExecution ou matchExpressions . - Oublier que nodeSelectorTerms est un tableau et doit contenir au moins un élément. Par exemple, cet extrait invalide : matchExpressions: - key: disktype operator: Equal values: [ssd, nvme] sera rejeté par le serveur API avec une erreur comme : The Deployment "my-deploy" is invalid: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values: Invalid value: []string{"ssd", "nvme"}: must be a single value for Equal operator Corrigez en utilisant operator: In avec plusieurs valeurs ou Equal avec une seule valeur. ### Étape 4 : Surveiller le planificateur en temps réel Si le pod reste en attente, surveillez les événements : kubectl get events --field-selector involvedObject.name= --watch Cela diffuse les messages du planificateur à mesure que des nœuds deviennent disponibles ou que les étiquettes changent. Cela aide à confirmer que votre correctif a pris effet sans attendre le prochain cycle de nouvelle tentative.
Question rapide 2 sur 2 Laquelle des listes d'opérateurs suivantes peut être utilisée dans les matchExpressions de node affinity ? - In, NotIn, Exists, DoesNotExist, Gt, Lt - Equal, NotEqual, Exists - In, Out, Exists - GreaterThan, LessThan, Equals
La référence indique : « Vous pouvez utiliser `In`, `NotIn`, `Exists`, `DoesNotExist`, `Gt` et `Lt`. »
## Modes de défaillance et récupération L'affinité de nœud peut échouer de plusieurs manières prévisibles. Chacune a une signature et une procédure de récupération spécifiques. ### Défaillance 1 : Aucun nœud ne satisfait l'affinité requise Symptôme : Pod bloqué en Pending . Les événements montrent 0/N nodes are available: N node(s) didn't match node affinity/selector . Cause : La règle requiredDuringSchedulingIgnoredDuringExecution est trop stricte ou les étiquettes manquent. Récupération : - Vérifiez les étiquettes des nœuds avec kubectl get nodes --show-labels . - Ajoutez les étiquettes manquantes à au moins un nœud. - Ou modifiez l'affinité pour être moins restrictive, par exemple, changez required... en preferred... si l'exigence n'est pas absolument obligatoire. Exemple de règle preferredDuringSchedulingIgnoredDuringExecution qui peut remplacer une règle required : affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: disktype operator: In values: - ssd Cela permet l'ordonnancement sur des nœuds sans disktype=ssd si aucun n'est disponible, mais les préfère lorsqu'ils sont présents. ### Défaillance 2 : Pod planifié sur le mauvais nœud car la règle préférée a ignoré d'autres contraintes Symptôme : Le pod s'exécute mais sur un nœud qui viole une attente métier. Cause : Les règles preferred sont souples. Le planificateur peut les ignorer si des contraintes strictes (comme les demandes de ressources) forcent un placement différent. Récupération : Convertissez la règle préférée en requise, ou ajoutez des règles requises supplémentaires. Vérifiez avec kubectl get pod -o wide pour voir le nœud. ### Défaillance 3 : Le planificateur plante ou devient indisponible Symptôme : Tous les pods en attente ne montrent aucun événement, ou kubectl describe pod ne montre aucun événement FailedScheduling mais le pod reste en attente. Cause : Le pod du planificateur est arrêté ou ne fonctionne pas. Récupération : Vérifiez la santé du planificateur : kubectl get pods -n kube-system | grep scheduler kubectl logs -n kube-system kube-scheduler- --tail=50 Si le planificateur est sain, le problème est ailleurs (par exemple, pas de ressources). S'il est arrêté, redémarrez-le ou enquêtez sur le nœud sous-jacent. ### Défaillance 4 : Conflit entre l'affinité de nœud et le sélecteur de nœud Symptôme : Pod en attente malgré des nœuds qui semblent correspondre. Cause : Vous avez défini à la fois nodeSelector et nodeAffinity . Le planificateur combine toutes les contraintes par ET logique, donc une inadéquation dans l'un ou l'autre empêche l'ordonnancement. Récupération : Supprimez l'un ou rendez-les cohérents. Vérifiez la spécification complète du pod : kubectl get pod -o yaml | grep -A5 nodeSelector Puis alignez les étiquettes. ## Liste de contrôle opérationnelle Utilisez cette liste avant et après l'application des modifications d'affinité de nœud pour minimiser les risques. ### Avant le changement - [ ] Exécutez kubectl get nodes --show-labels et enregistrez l'ensemble des étiquettes. - [ ] Identifiez au moins un nœud qui correspond à votre règle d'affinité prévue. - [ ] Confirmez que la version de Kubernetes prend en charge votre syntaxe d'affinité (toutes les versions stables le font, mais vérifiez si vous utilisez des fonctionnalités bêta). - [ ] Sauvegardez la spécification actuelle du déploiement/pod : kubectl get deploy my-deploy -o yaml > deploy-backup.yaml . - [ ] Testez la nouvelle règle d'affinité avec un pod minimal dans un espace de noms de développement. - [ ] Assurez-vous d'avoir la permission d'étiqueter les nœuds si votre correctif nécessite des modifications d'étiquettes. ### Après le changement - [ ] Appliquez le manifeste modifié et surveillez le déploiement : kubectl rollout status deployment/my-deploy . - [ ] Vérifiez le placement des pods : kubectl get pods -o wide montre le nœud attendu. - [ ] Vérifiez les événements pour les erreurs d'ordonnancement : kubectl describe pod . - [ ] Si le pod est en attente, capturez le message du planificateur avant de revenir en arrière. - [ ] Documentez le correctif et les modifications d'étiquettes dans votre runbook. Exemple de déploiement complet avec affinité de nœud après un correctif : apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 3 selector: matchLabels: app: web template: metadata: labels: app: web spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - us-east-1a - us-east-1b preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExpressions: - key: disktype operator: In values: - ssd containers: - name: nginx image: nginx:1.25 Cela exige que les pods s'exécutent dans les zones us-east-1a ou us-east-1b , et préfère les nœuds avec disktype=ssd . Vérifiez avec : kubectl apply -f web-deploy.yaml kubectl get pods -o wide Tous les pods doivent être en état Running et leur colonne NODE doit montrer des nœuds dans les zones autorisées. ## Conclusion Les erreurs d'affinité de nœud sont presque toujours visibles dans les événements du pod, et le correctif implique généralement d'aligner les étiquettes avec vos expressions d'affinité. En suivant les étapes de diagnostic de cet article — vérifiez d'abord les étiquettes, validez ensuite la syntaxe de l'affinité, puis surveillez le planificateur — vous pouvez résoudre la plupart des problèmes en quelques minutes. Rappelez-vous que requiredDuringSchedulingIgnoredDuringExecution est une contrainte stricte : si aucun nœud ne correspond, le pod ne sera jamais planifié. Utilisez preferredDuringSchedulingIgnoredDuringExecution pour des préférences souples qui ne doivent pas bloquer l'ordonnancement. Testez toujours dans un espace de noms de développement, conservez une sauvegarde de votre manifeste d'origine et documentez tout changement d'étiquette. Un flux de travail fiable rend les échecs visibles, protège les valeurs sensibles et définit la vérification de la récupération avant qu'un incident ne force la décision. Avec les exemples pratiques présentés ici, vous pouvez aborder la configuration et le dépannage de l'affinité de nœud avec confiance.