Introduction
L'affinité de nœud Kubernetes vous donne un contrôle précis sur l'emplacement des pods. Mais un contrôle sans planification de capacité conduit à des pods non planifiables, des nœuds gaspillés et des incidents douloureux. Ce guide présente une approche pratique de la planification de capacité de l'affinité de nœud : inventaire des versions et de l'environnement, configuration sûre, vérification, modes de défaillance et listes de contrôle opérationnelles. Vous trouverez des commandes concrètes, des extraits de manifestes et des exemples détaillés pour appliquer ces étapes à vos propres clusters.
Nous supposons une familiarité de base avec la planification Kubernetes. Vous devez savoir exécuter kubectl et lire les événements des pods. L'accent est mis sur l'affinité de nœud, mais nous mentionnerons l'affinité et l'anti-affinité de pod lorsque cela affecte les décisions de capacité.
L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le risque, utiliser des espaces réservés plutôt que des secrets, vérifier le résultat et documenter la récupération avant qu'un incident ne vous force la main.
Inventaire des versions et de l'environnement
Avant de planifier la capacité de l'affinité de nœud, sachez avec quoi vous travaillez. Exécutez ces commandes pour capturer l'état actuel. Enregistrez la sortie et horodatez-la.
- Vérifiez la version du serveur Kubernetes :
kubectl version --short
La sortie attendue inclut la version du serveur, par exemple : Server Version: v1.27.3.
- Listez les nœuds et leurs labels :
kubectl get nodes --show-labels
Cela montre tous les nœuds avec des labels comme topology.kubernetes.io/zone=us-east-1a et tout label personnalisé que vous avez ajouté.
- Vérifiez les pods existants et où ils s'exécutent :
kubectl get pods -o wide
Regardez la colonne NODE pour voir la distribution actuelle.
- Décrivez tout pod en attente ou en échec pour voir les événements de planification :
kubectl describe pod <nom-du-pod>
Les événements indiqueront si l'affinité de nœud empêche la planification.
- Vérifiez l'état du déploiement avant de supposer qu'une version a réussi :
kubectl rollout status deployment/<nom-du-déploiement>
Ensuite, identifiez les labels de nœud que vous prévoyez d'utiliser pour l'affinité. Vous devez connaître la clé et la valeur. Par exemple, si vous prévoyez de planifier uniquement sur des nœuds avec disktype=ssd, vérifiez combien de nœuds ont ce label :
kubectl get nodes -l disktype=ssd
Ce compte est essentiel pour la planification de capacité. Si un seul nœud a le label et que vous avez besoin de trois réplicas pour la haute disponibilité, vous avez un problème.
Notez également la version de Kubernetes : l'affinité de nœud est stable depuis la v1.6, mais les versions plus récentes peuvent avoir des fonctionnalités supplémentaires comme des améliorations de requiredDuringSchedulingIgnoredDuringExecution. Vérifiez la compatibilité de votre version.
Prérequis pour cette étape : accès au cluster avec des permissions de lecture pour les nœuds et les pods. Utilisez d'abord des commandes en lecture seule. Ne modifiez rien tant que vous ne comprenez pas la base.
Gardez votre test local petit. Appliquez un manifeste, inspectez les ressources générées et vérifiez le trafic avec kubectl port-forward ou un type de service local avant de passer à un équilibreur de charge cloud ou à un contrôleur d'entrée.
Chemin de configuration sûr
L'affinité de nœud est définie dans la spécification du pod sous affinity.nodeAffinity. Il existe deux types : requiredDuringSchedulingIgnoredDuringExecution (dure) et preferredDuringSchedulingIgnoredDuringExecution (douce). L'affinité dure exige que le nœud corresponde ; l'affinité douce est une préférence.
Voici un exemple minimal d'affinité dure :
apiVersion: v1
kind: Pod
metadata:
name: nginx-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx:1.25
Ce pod ne sera planifié que sur des nœuds avec le label disktype=ssd.
Pour la planification de capacité, vous devez considérer combien de tels nœuds existent et leurs ressources disponibles. Utilisez :
kubectl describe node <nœud-avec-label>
pour voir le CPU et la mémoire allouables. Additionnez les demandes des pods qui utiliseront cette affinité.
Une approche plus sûre consiste à commencer par l'affinité douce, qui permet la planification même si aucun nœud correspondant n'est disponible :
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
Ce pod préférera les nœuds ssd mais peut s'exécuter ailleurs.
Avant d'appliquer tout changement, vérifiez que le label existe. Si vous définissez une affinité dure pour un label qu'aucun nœud n'a, le pod sera non planifiable. Vérifiez avec :
kubectl get nodes -L disktype
Si vous devez ajouter un label à un nœud :
kubectl label node <nom-du-nœud> disktype=ssd
Mais soyez prudent : ce changement affecte tous les pods avec cette affinité.
Appliquez toujours les changements dans un espace de noms de test ou de staging d'abord. Utilisez --dry-run=client pour prévisualiser :
kubectl apply -f pod.yaml --dry-run=client
Ensuite, appliquez et surveillez :
kubectl apply -f pod.yaml
kubectl get pods -o wide
Vérifiez que le pod atterrit sur le nœud prévu.
Vérification et diagnostic
Après avoir configuré l'affinité de nœud, vous devez vérifier que la planification fonctionne comme prévu et que la capacité est suffisante.
- Vérifiez le placement du pod :
kubectl get pods -o wide
Confirmez que le pod est sur un nœud avec le label correspondant.
- Si un pod est en attente, décrivez-le pour voir pourquoi :
kubectl describe pod <nom-du-pod>
Cherchez des événements comme :
Warning FailedScheduling 2m (x5 over 10m) default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector.
Cela indique qu'aucun nœud ne correspond à l'affinité.
- Consultez les journaux du planificateur si nécessaire. Dans un cluster géré, vous n'y avez peut-être pas accès, mais dans un cluster autogéré, vous pouvez regarder :
kubectl logs -n kube-system kube-scheduler-<nom-du-nœud>
Cela peut montrer un raisonnement détaillé.
- Vérifiez que le nœud a suffisamment de ressources. Utilisez :
kubectl describe node <nom-du-nœud>
Regardez la section Allocated resources et comparez avec Allocatable. Par exemple, si un nœud a 4 CPU allouables et que les pods existants demandent 3,5 CPU, un nouveau pod demandant 1 CPU ne tiendra pas, provoquant un état d'attente.
- Testez avec un pod simple sans affinité pour confirmer que le cluster est sain.
Simulez également des scénarios de capacité. Par exemple, si vous avez 10 pods nécessitant des nœuds SSD et seulement 5 nœuds SSD, estimez si chaque nœud peut gérer 2 pods. Vérifiez les demandes de ressources par pod :
resources:
requests:
cpu: "500m"
memory: "512Mi"
Si chaque nœud SSD a 4 CPU allouables, 2 pods par nœud sont sûrs. Si chaque pod demande 2 CPU, vous avez besoin de 10 nœuds ou réduisez les réplicas.
Documentez vos résultats. Tenez une feuille de capacité : label, nombre de nœuds, CPU/mémoire allouables totaux, somme des demandes de pods pour ce label.
Modes de défaillance et récupération
Une mauvaise configuration de l'affinité de nœud peut causer plusieurs modes de défaillance. Comprenez-les et sachez comment récupérer.
1. Pods bloqués en attente en raison de l'absence de nœuds correspondants
- Pourquoi cela arrive : le label d'affinité n'existe sur aucun nœud, ou aucun nœud avec ce label n'a assez de ressources.
- Comment détecter :
kubectl get podsmontre en attente ;kubectl describe podmontredidn't match node selector. - Récupération : supprimez ou assouplissez temporairement l'affinité, ou ajoutez des labels à plus de nœuds (si approprié), ou réduisez les réplicas.
- Exemple : si vous avez une affinité dure pour
zone=us-east-1amais que tous les nœuds de cette zone sont en panne, les pods seront en attente. Passez à une affinité douce ou ajoutez des nœuds.
2. Distribution inégale causant une pression sur les ressources
- Pourquoi cela arrive : de nombreux pods avec la même affinité atterrissent sur peu de nœuds, les surchargeant alors que d'autres nœuds sont inactifs.
- Comment détecter : utilisez
kubectl top nodesetkubectl top podspour voir l'utilisation des ressources. CPU/mémoire élevés sur les nœuds d'affinité. - Récupération : ajoutez plus de nœuds avec ce label, ou ajustez les demandes et limites des pods, ou utilisez l'anti-affinité de pod pour répartir les pods entre les nœuds.
3. Les changements de labels cassent la planification existante
- Pourquoi cela arrive : quelqu'un supprime ou modifie un label de nœud dont dépendent les pods.
- Comment détecter : les pods en cours d'exécution peuvent être expulsés si l'affinité de nœud est
requiredDuringSchedulingIgnoredDuringExecutionet que le label est supprimé ? En fait,IgnoredDuringExecutionsignifie que les pods en cours d'exécution ne sont pas expulsés si le label change, mais les nouveaux pods ou pods replanifiés échoueront. Surveillez donc les nouveaux pods en attente. - Récupération : restaurez le label, ou mettez à jour l'affinité du pod.
4. Capacité insuffisante pour une montée en charge planifiée
- Pourquoi cela arrive : vous prévoyez de mettre à l'échelle un déploiement mais n'avez pas tenu compte des contraintes d'affinité de nœud ; les nouveaux réplicas ne peuvent pas être planifiés.
- Comment détecter : lors de la mise à l'échelle,
kubectl get podsmontre de nouveaux pods en attente. - Récupération : ajoutez des nœuds avec les labels requis, ou assouplissez l'affinité, ou réduisez la cible de mise à l'échelle.
Liste de contrôle de récupération :
- Ayez toujours un plan de retour en arrière. Pour les déploiements, utilisez
kubectl rollout undo deployment/<nom>. - Gardez la configuration d'affinité dans le contrôle de version pour permettre une restauration rapide.
- Testez régulièrement les procédures de récupération.
Liste de contrôle opérationnelle
Pour une planification continue de la capacité de l'affinité de nœud, utilisez cette liste de contrôle. Attribuez un propriétaire et une fréquence de révision.
- Inventaire des labels de nœud : listez tous les labels personnalisés et leur objectif. Propriétaire : Administrateur de cluster (ex. : Priya Shah). Révision mensuelle.
- Comptez les nœuds par label : sortie de
kubectl get nodes -L <label>. Propriétaire : Équipe DevOps (ex. : Mark Chen). Révision lors de changements. - Surveillez les pods en attente en raison de l'affinité : configurez une alerte sur
kubectl get pods --field-selector=status.phase=Pending. Propriétaire : SRE (ex. : Luis Alvarez). Révision quotidienne. - Suivez l'utilisation des ressources par groupe d'affinité : utilisez le serveur de métriques et des tableaux de bord personnalisés. Propriétaire : Planificateur de capacité (ex. : Sarah Kim). Révision hebdomadaire.
- Validez les nouvelles règles d'affinité avant déploiement : utilisez dry-run et un espace de noms de test. Propriétaire : Chef d'équipe applicative (ex. : David Lee). Révision par changement.
- Documentez les seuils de capacité : pour chaque groupe de labels, définissez l'utilisation maximale CPU/mémoire (ex. : 80 %). Propriétaire : Planificateur de capacité. Révision trimestrielle.
- Planifiez les ajouts de nœuds : alignez-vous avec le fournisseur cloud ou l'équipe matérielle. Propriétaire : Responsable infrastructure (ex. : Emily Davis). Révision trimestrielle.
Exemples de métriques de tableau de bord :
- Somme des demandes de pods pour le label
disktype=ssdvs total allouable sur les nœuds ssd. - Nombre de pods en attente avec incompatibilité d'affinité.
- Utilisation des nœuds par label.
Commandes de surveillance :
# Vérifier les pods en attente
kubectl get pods --all-namespaces --field-selector=status.phase=Pending
# Afficher les ressources des nœuds
kubectl describe nodes | grep -A 5 "Allocated resources"
# Obtenir les demandes de pods par nœud (en utilisant un script personnalisé)
kubectl get pods -o json | jq '[.items[] | .spec.containers[].resources.requests.cpu // "0"] | map(tonumber) | add'
Pièges courants
Évitez ces erreurs dans la planification de capacité de l'affinité de nœud.
Piège 1 : Ignorer l'affinité douce vs dure De nombreuses équipes utilisent l'affinité dure pour chaque exigence, causant des échecs de planification inutiles. Utilisez l'affinité dure uniquement pour les exigences strictes (ex. : conformité, matériel). Pour les préférences, utilisez l'affinité douce. Pourquoi cela arrive : l'affinité dure semble plus sûre mais réduit la flexibilité. Comment éviter : évaluez chaque règle d'affinité : si un pod peut s'exécuter ailleurs, utilisez la douce. Récupération : changez la dure en douce dans la spécification du pod et appliquez.
Piège 2 : Ne pas considérer les demandes de pods dans la planification de capacité L'affinité assure uniquement le placement sur certains nœuds, mais si les ressources sont insuffisantes, les pods restent en attente. Additionnez toujours les demandes de pods et comparez avec l'allouable du nœud. Pourquoi cela arrive : les équipes se concentrent sur les labels, pas sur les ressources. Comment éviter : incluez les demandes de ressources dans tous les pods et calculez le total par groupe de nœuds. Récupération : ajustez les demandes ou ajoutez des nœuds.
Piège 3 : Ajouter des labels sans coordination Si plusieurs équipes utilisent le même label, le modifier peut causer des échecs généralisés. Coordonnez les changements de labels. Pourquoi cela arrive : absence de gestion centrale des labels. Comment éviter : maintenez un registre de labels et un processus de contrôle des changements. Récupération : revenez sur le label et communiquez.
Piège 4 : Oublier l'anti-affinité L'affinité seule peut faire atterrir tous les réplicas sur un nœud, réduisant la disponibilité. Utilisez l'anti-affinité de pod pour répartir les pods. Exemple :
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
Cela garantit qu'aucun deux pods de la même application ne sont sur le même nœud. Pourquoi cela arrive : négligé car l'affinité est le centre d'attention. Comment éviter : considérez toujours l'anti-affinité pour la haute disponibilité. Récupération : ajoutez l'anti-affinité et mettez à jour le déploiement.
Piège 5 : S'appuyer sur un suivi manuel de la capacité Les feuilles de calcul manuelles deviennent rapidement obsolètes. Utilisez les API Kubernetes et les outils pour suivre la capacité automatiquement. Pourquoi cela arrive : simplicité initiale, puis dérive. Comment éviter : mettez en place la surveillance et les alertes dès le premier jour. Récupération : implémentez des tableaux de bord automatisés.
Conclusion
La planification de capacité de l'affinité de nœud est un processus continu, pas une configuration unique. En inventoriant votre environnement, en configurant en toute sécurité l'affinité avec des règles dures et douces, en vérifiant le placement et les ressources, en vous préparant aux modes de défaillance et en suivant une liste de contrôle opérationnelle, vous pouvez prévenir les surprises de planification. Testez toujours dans un espace de noms de staging, utilisez dry-run et documentez les étapes de récupération. Attribuez des propriétaires clairs et examinez régulièrement les métriques de capacité. Avec ces pratiques, vous transformez l'affinité de nœud d'un goulot d'étranglement potentiel en un composant fiable de votre stratégie Kubernetes.
Ensuite, choisissez une vérification à faible risque de ce guide, enregistrez l'état actuel, exécutez la vérification et comparez avec le signal attendu. Passez ensuite en revue les dépendances comme l'affinité/anti-affinité de pod et les labels de nœud. Un flux de travail fiable rend les défaillances visibles, protège les valeurs sensibles et limite les changements aux ressources prévues.