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 <none> 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.
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 <nom-du-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: Equalavec plusieurs valeurs (invalide ;Equalaccepte exactement une valeur). - Utiliser
operator: Inmais laisservaluesvide. - Mal orthographier
requiredDuringSchedulingIgnoredDuringExecutionoumatchExpressions. - Oublier que
nodeSelectorTermsest 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=<nom-du-pod> --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.
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...enpreferred...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-<nœud-du-plan-de-contrôle> --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 <nom> -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-labelset 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 widemontre le nœud attendu. - [ ] Vérifiez les événements pour les erreurs d'ordonnancement :
kubectl describe pod <nouveau-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.