Introduction
Les règles d'affinité et d'anti-affinité des pods dans Kubernetes vous permettent de contrôler sur quels nœuds vos pods sont placés, en fonction des étiquettes des autres pods s'exécutant sur ces nœuds. C'est un outil puissant pour optimiser la latence, améliorer la résilience et imposer une colocalisation ou une séparation. Cependant, des erreurs de configuration conduisent souvent à des pods bloqués en état « Pending », à une planification inattendue ou à des inefficacités au niveau du cluster. Ce guide passe en revue les erreurs les plus courantes, comment les diagnostiquer et les corriger en toute sécurité avec des exemples pratiques.
Inventaire des versions et de l'environnement
Avant de résoudre les problèmes d'affinité, établissez une base de référence de votre environnement. Vérifiez la version de Kubernetes, car la syntaxe et le comportement de l'affinité ont évolué. Utilisez kubectl version --short pour voir les versions client et serveur. Par exemple :
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.24.3
Server Version: v1.24.3
Remarque : Dans les versions plus récentes, --short est obsolète ; utilisez kubectl version sans drapeaux.
Ensuite, comprenez la topologie de votre cluster. Pour que l'affinité fonctionne, les nœuds doivent posséder les étiquettes pertinentes. Par exemple, pour une clé de topologie comme topology.kubernetes.io/zone, chaque nœud doit avoir une étiquette de zone. Listez les nœuds avec leurs étiquettes :
kubectl get nodes --show-labels
Recherchez des étiquettes telles que kubernetes.io/hostname, topology.kubernetes.io/zone, topology.kubernetes.io/region ou des étiquettes personnalisées comme disktype=ssd.
Prérequis :
- Un cluster avec au moins deux nœuds (pour démontrer l'anti-affinité).
kubectlconfiguré avec accès au cluster.- Compréhension des étiquettes et des sélecteurs.
Chemin de configuration sûr
Commencez par un exemple minimal et testez dans un espace de noms non productif si possible. Nous créons ici un scénario : une application web et un cache qui doivent être colocalisés (affinité), et des réplicas web qui doivent être répartis sur les nœuds (anti-affinité).
Exemple : Affinité de pods
Nous voulons qu'un pod web soit planifié sur un nœud qui exécute déjà un pod avec l'étiquette app=cache. Définissez le pod comme suit :
apiVersion: v1
kind: Pod
metadata:
name: web-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
Appliquez-le :
kubectl apply -f web-affinity.yaml
Si aucun pod cache n'existe, le pod web restera en état « Pending ». C'est une erreur courante : affinité non satisfaisable. Nous couvrirons le diagnostic plus tard.
Exemple : Anti-affinité de pods
Pour répartir les pods web sur les nœuds, utilisez l'anti-affinité avec topologyKey: kubernetes.io/hostname :
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
Cela garantit qu'aucun pod web de ce déploiement ne s'exécute sur le même nœud. Si vous avez moins de nœuds que de réplicas, les pods resteront en attente.
Vérification et diagnostics
Vérification du statut des pods
Pour voir si les pods ne peuvent pas être planifiés en raison de l'affinité, utilisez :
kubectl get pods
Recherchez les pods avec le statut Pending. Décrivez ensuite le pod :
kubectl describe pod <nom-du-pod>
Dans la section Événements, recherchez des messages comme :
Warning FailedScheduling 2m (x25 over 5m) default-scheduler 0/3 nodes are available: 1 node(s) didn't match pod affinity/anti-affinity, 2 node(s) didn't match pod anti-affinity rules.
Cela indique que le planificateur n'a pas trouvé de nœud satisfaisant les règles.
Vérification des étiquettes des nœuds
Assurez-vous que toutes les clés de topologie utilisées dans vos règles d'affinité ont des étiquettes correspondantes sur les nœuds. Par exemple, si vous utilisez topologyKey: topology.kubernetes.io/zone, vérifiez les nœuds :
kubectl get nodes -L topology.kubernetes.io/zone
Si un nœud n'a pas l'étiquette, il ne sera pas pris en compte pour les pods utilisant cette clé de topologie.
Simulation de planification
Il n'existe pas de simulation intégrée pour la planification, mais vous pouvez utiliser des outils comme le planificateur Kubernetes en mode débogage ou des validateurs tiers. Une vérification plus simple consiste à réduire temporairement le nombre de réplicas pour voir si un pod peut être planifié.
Modes de défaillance et récupération
Erreurs courantes et correctifs
- Affinité de pods non satisfaisable : Le pod requiert une étiquette qu'aucun pod existant n'a. Correctif : assurez-vous que le pod cible existe et possède la bonne étiquette. Exemple : avant d'appliquer
web-affinity.yaml, créez un pod cache :
apiVersion: v1
kind: Pod
metadata:
name: cache-pod
labels:
app: cache
spec:
containers:
- name: redis
image: redis
Appliquez ensuite le pod web. Il devrait être planifié sur le même nœud.
- Clé de topologie manquante sur les nœuds : Si les nœuds n'ont pas l'étiquette de clé de topologie, les pods utilisant cette clé ne pourront pas être planifiés. Correctif : ajoutez l'étiquette aux nœuds :
kubectl label nodes <nom-du-nœud> topology.kubernetes.io/zone=us-east-1a
- Pas assez de nœuds pour l'anti-affinité : Si vous exigez une anti-affinité avec
requiredDuringSchedulinget que vous avez plus de réplicas que de nœuds, certains pods resteront en attente. Correctif : augmentez le nombre de nœuds, utilisezpreferredDuringSchedulingpour une anti-affinité douce, ou réduisez le nombre de réplicas.
- Incohérence du sélecteur d'étiquettes : Assurez-vous que le sélecteur d'étiquettes dans l'affinité correspond aux étiquettes des pods que vous voulez attirer ou repousser. Utilisez
kubectl get pods --show-labelspour vérifier.
- Clé de topologie invalide : Si la clé de topologie n'est pas une clé d'étiquette valide, le pod sera rejeté par le serveur d'API. Exemple : utiliser
topologyKey: "failure-domain.beta.kubernetes.io/zone"qui est obsolète dans les versions plus récentes. Utiliseztopology.kubernetes.io/zoneà la place.
Retour en arrière et récupération
Si une règle d'affinité cause une panne, supprimez ou modifiez la section d'affinité dans la spécification du pod. Pour un déploiement, mettez à jour le modèle de pod :
kubectl edit deployment web-deploy
Supprimez le bloc d'affinité ou modifiez-le. Supprimez ensuite les pods en attente pour forcer la recréation :
kubectl delete pods -l app=web
Pour un pod unique, supprimez-le et réappliquez sans affinité.
Pièges courants et comment les éviter
1. Règles d'affinité trop restrictives
Pourquoi cela arrive : Utiliser requiredDuringScheduling avec des termes d'affinité complexes ou multiples peut rendre presque impossible pour le planificateur de trouver un nœud approprié. Par exemple, exiger à la fois une zone spécifique et une étiquette de nom d'hôte spécifique peut être insatisfaisable dans un petit cluster.
Comment éviter : Préférez preferredDuringScheduling pour les contraintes non critiques. Si vous devez utiliser required, testez d'abord dans un environnement de préproduction. Assurez-vous également que les clés de topologie que vous utilisez ont suffisamment de nœuds par domaine.
Récupération : Si les pods sont bloqués, modifiez le déploiement pour utiliser preferredDuringScheduling ou assouplissez le sélecteur. Supprimez les pods bloqués pour les replanifier.
2. Ignorer les étiquettes des nœuds
Pourquoi cela arrive : Supposer que les nœuds ont des étiquettes standard comme topology.kubernetes.io/zone alors qu'ils ne les ont pas, en particulier dans les clusters personnalisés ou sur site.
Comment éviter : Vérifiez toujours les étiquettes des nœuds avant d'écrire des règles d'affinité. Utilisez kubectl get nodes --show-labels et assurez-vous que les étiquettes requises sont présentes. Sinon, ajoutez-les manuellement ou via les étiquettes de nœuds dans votre infrastructure.
Récupération : Ajoutez les étiquettes manquantes aux nœuds en utilisant kubectl label nodes.
3. Oublier de mettre à jour les étiquettes lors du passage à l'échelle
Pourquoi cela arrive : Lorsque de nouveaux nœuds sont ajoutés au cluster, ils peuvent ne pas avoir les mêmes étiquettes personnalisées que les nœuds existants, ce qui entraîne un comportement de planification incohérent.
Comment éviter : Utilisez l'infrastructure comme code pour étiqueter automatiquement les nœuds, ou au moins ayez un runbook pour étiqueter les nouveaux nœuds.
Récupération : Étiquetez les nouveaux nœuds selon les besoins et supprimez les pods en attente pour les replanifier.
4. Confondre affinité de pods et affinité de nœuds
Pourquoi cela arrive : L'affinité de pods est basée sur les étiquettes d'autres pods, tandis que l'affinité de nœuds est basée sur les étiquettes des nœuds. Une mauvaise compréhension peut conduire à des sélecteurs et des clés de topologie incorrects.
Comment éviter : Comprenez clairement la différence : l'affinité de pods utilise podAffinity ou podAntiAffinity dans la spécification du pod et sélectionne des pods, tandis que l'affinité de nœuds utilise nodeAffinity et sélectionne des nœuds. Vérifiez toujours que le sélecteur correspond au type de ressource prévu.
Récupération : Examinez le YAML pour le bon type d'affinité et corrigez le sélecteur en conséquence.
5. Utiliser des clés de topologie obsolètes
Pourquoi cela arrive : La documentation et les exemples plus anciens peuvent encore utiliser des clés obsolètes comme failure-domain.beta.kubernetes.io/zone ou beta.kubernetes.io/arch.
Comment éviter : Tenez-vous-en aux étiquettes stables topology.kubernetes.io/*. L'étiquette kubernetes.io/hostname est toujours valide.
Récupération : Remplacez les clés obsolètes par les stables et réappliquez.
6. Ne pas tenir compte de la capacité de planification
Pourquoi cela arrive : Les règles d'anti-affinité requises limitent la densité des pods. Si vous avez plus de réplicas que de nœuds disponibles, certains pods ne seront jamais planifiés.
Comment éviter : Utilisez preferredDuringScheduling pour l'anti-affinité lorsque c'est possible, ou assurez-vous d'avoir suffisamment de nœuds pour satisfaire le nombre de réplicas. Envisagez d'utiliser des contraintes de répartition de la topologie des pods pour une répartition plus flexible.
Récupération : Réduisez le nombre de réplicas, ajoutez des nœuds ou passez à une anti-affinité préférée.
Liste de contrôle opérationnelle
- Confirmez la version de Kubernetes et que les étiquettes existent sur les nœuds.
- Validez que les sélecteurs d'étiquettes dans les règles d'affinité correspondent aux étiquettes des pods existants.
- Assurez-vous que la clé de topologie est correcte et présente sur tous les nœuds concernés.
- Préférez
preferredDuringSchedulingpour les contraintes douces afin d'éviter les blocages durs. - Surveillez les événements des pods pour détecter les échecs de planification.
- Testez les règles d'affinité dans un espace de noms de préproduction avant la production.
- Gardez les étiquettes des nœuds à jour, en particulier lors de l'ajout de nouveaux nœuds.
- Utilisez
kubectl describepour identifier rapidement les pods non planifiables et les raisons. - Documentez vos politiques d'affinité pour référence par l'équipe.
Conclusion
L'affinité et l'anti-affinité des pods sont précieuses pour contrôler le placement des pods, mais elles nécessitent une configuration soignée. En comprenant les erreurs courantes telles que les règles insatisfaisables, les étiquettes manquantes et les problèmes de clé de topologie, vous pouvez rapidement diagnostiquer et corriger les problèmes de planification. Commencez toujours par un test simple, vérifiez les étiquettes et envisagez d'utiliser des contraintes douces pour une meilleure résilience. Révisez régulièrement vos politiques de planification pour les aligner sur la capacité du cluster et les besoins des applications.