Introduction
L'ordonnancement Kubernetes détermine où les pods s'exécutent dans un cluster. Alors que l'affinité de nœuds et les sélecteurs de nœuds attirent les pods vers des nœuds spécifiques, les taints et les tolérances fournissent le mécanisme inverse : repousser les pods des nœuds. Les taints sont appliqués aux nœuds et les tolérances sont appliquées aux pods. Un pod ne peut être planifié sur un nœud taché que s'il possède une tolérance correspondante. Ce guide explique l'architecture, le flux de données, le flux de contrôle et l'utilisation pratique des taints et des tolérances, avec des commandes concrètes, des scénarios de défaillance et une liste de contrôle opérationnelle.
Les taints et les tolérances sont des contraintes d'ordonnancement, pas des fonctionnalités de sécurité. Ils influencent le planificateur par défaut mais n'empêchent pas un pod de s'exécuter sur un nœud si le pod y est lié par d'autres moyens, comme un contrôleur qui contourne l'ordonnancement. Comprendre cette distinction est essentiel pour concevoir des stratégies d'isolation de cluster robustes.
Cet article couvre la configuration de la version et de l'environnement, les chemins de configuration sûrs, la vérification et le diagnostic, les modes de défaillance et la récupération, ainsi qu'une liste de contrôle opérationnelle reproductible. Chaque section inclut des commandes et des exemples que vous pouvez exécuter dans un bac à sable ou un cluster de test.
Inventaire des versions et de l'environnement
Établir une base cohérente est la première étape. Les exemples de ce guide utilisent Kubernetes 1.25, une version largement déployée qui prend en charge toutes les fonctionnalités discutées. La plupart des concepts sont rétrocompatibles, mais vérifiez toujours les notes de version de votre cluster.
Topologie du cluster
Supposons un cluster avec au moins trois nœuds : un nœud plan de contrôle et deux nœuds travailleurs. Le nœud plan de contrôle a généralement un taint node-role.kubernetes.io/control-plane:NoSchedule pour empêcher les charges de travail ordinaires d'y être planifiées. Les nœuds travailleurs commencent sans taint. Le tableau suivant résume la configuration initiale :
| Nom du nœud | Rôle | Taints |
|---|---|---|
| control-plane-1 | plan de contrôle | node-role.kubernetes.io/control-plane: NoSchedule |
| worker-1 | travailleur | <aucun> |
| worker-2 | travailleur | <aucun> |
Prérequis
- Un cluster Kubernetes en cours d'exécution (version 1.25 ou ultérieure) avec
kubectlconfiguré. - Des privilèges d'administrateur de cluster pour appliquer des taints aux nœuds.
- Une familiarité de base avec les Pods, les Deployments et les nœuds.
Concepts clés
- Taint : une paire clé-valeur avec un effet (
NoSchedule,PreferNoScheduleouNoExecute) appliquée à un nœud. - Tolérance : une spécification dans un pod qui lui permet d'être planifié sur des nœuds avec des taints correspondants.
- Effet : détermine comment le taint affecte les pods qui ne le tolèrent pas :
NoSchedule: empêche la planification de nouveaux pods sur le nœud ; les pods existants restent.PreferNoSchedule: le planificateur essaie d'éviter de placer des pods sur le nœud mais ne garantit pas l'évitement.NoExecute: évince les pods existants qui ne tolèrent pas le taint et empêche les nouveaux.
Chemin de configuration sûr
Procédez progressivement lors de la mise en œuvre des taints. Commencez par l'effet le moins perturbateur, PreferNoSchedule, puis passez à NoSchedule, et enfin NoExecute si nécessaire. Cela minimise le risque d'évictions involontaires. Chaque étape comprend des commandes et des sorties attendues.
Étape 1 : Inspecter les taints actuels
Exécutez :
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
Sortie attendue :
NAME TAINTS
control-plane-1 [map[effect:NoSchedule key:node-role.kubernetes.io/control-plane]]
worker-1 <aucun>
worker-2 <aucun>
Le nœud plan de contrôle est taché et les nœuds travailleurs n'ont aucun taint. Tous les pods sans tolérances spéciales peuvent être planifiés sur les travailleurs.
Étape 2 : Appliquer un taint PreferNoSchedule
Utilisez PreferNoSchedule pour orienter doucement les pods loin d'un nœud. Par exemple, pour marquer worker-2 comme préféré pour une équipe, exécutez :
kubectl taint nodes worker-2 team=blue:PreferNoSchedule
Sortie :
node/worker-2 tainted
Créez un pod de test sans tolérance :
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx
Appliquez-le :
kubectl apply -f test-pod.yaml
Vérifiez le placement du nœud :
kubectl get pod test-pod -o wide
Sortie attendue :
NAME READY STATUS RESTARTS AGE IP NODE
test-pod 1/1 Running 0 5s 10.244.1.5 worker-1
Le pod est planifié sur worker-1 car worker-2 a un taint PreferNoSchedule, le rendant moins préféré. Cependant, si les deux travailleurs étaient tachés, le pod serait quand même planifié sur l'un d'eux car PreferNoSchedule est une préférence douce.
Étape 3 : Appliquer un taint NoSchedule
Pour une isolation plus stricte, utilisez NoSchedule. Cela empêche les nouveaux pods sans tolérances correspondantes d'être planifiés sur le nœud taché. Appliquez à worker-2 :
kubectl taint nodes worker-2 team=blue:NoSchedule --overwrite
Sortie :
node/worker-2 tainted
Supprimez et recréez le pod de test :
kubectl delete pod test-pod
kubectl apply -f test-pod.yaml
Vérifiez le nœud :
kubectl get pod test-pod -o wide
Sortie attendue :
NAME READY STATUS RESTARTS AGE IP NODE
test-pod 1/1 Running 0 3s 10.244.1.6 worker-1
Le pod reste sur worker-1 car worker-2 a un taint NoSchedule et le pod n'a pas de tolérance. Pour autoriser un pod sur worker-2, ajoutez une tolérance :
apiVersion: v1
kind: Pod
metadata:
name: tolerated-pod
spec:
tolerations:
- key: "team"
operator: "Equal"
value: "blue"
effect: "NoSchedule"
containers:
- name: nginx
image: nginx
Appliquez :
kubectl apply -f tolerated-pod.yaml
Vérifiez le nœud :
kubectl get pod tolerated-pod -o wide
Sortie attendue :
NAME READY STATUS RESTARTS AGE IP NODE
tolerated-pod 1/1 Running 0 4s 10.244.2.7 worker-2
La tolérance permet au pod d'être planifié sur le nœud taché.
Étape 4 : Appliquer un taint NoExecute
NoExecute évince les pods existants qui ne tolèrent pas le taint. Il est utile pour la maintenance des nœuds ou la dédicace stricte. Appliquez à worker-2 :
kubectl taint nodes worker-2 team=blue:NoExecute --overwrite
Sortie :
node/worker-2 tainted
Tout pod sur worker-2 qui ne tolère pas ce taint est évincé immédiatement. Le tolerated-pod reste car il a une tolérance correspondante. Pour démontrer l'éviction, créez un pod forcé sur worker-2 en utilisant nodeName (en contournant le planificateur) :
apiVersion: v1
kind: Pod
metadata:
name: evicted-pod
spec:
nodeName: worker-2
containers:
- name: nginx
image: nginx
Appliquez :
kubectl apply -f evicted-pod.yaml
Vérifiez l'état après quelques secondes :
kubectl get pod evicted-pod
Sortie attendue :
NAME READY STATUS RESTARTS AGE
evicted-pod 0/1 Terminating 0 5s
Le taint NoExecute a évincé le pod car il n'a pas de tolérance. Utilisez NoExecute avec une extrême prudence et assurez-vous que les pods système critiques ont des tolérances appropriées au préalable.
Étape 5 : Supprimer un taint
Annulez un taint en utilisant kubectl taint avec un signe moins après l'effet :
kubectl taint nodes worker-2 team=blue:NoExecute-
Sortie :
node/worker-2 untainted
Vérifiez la suppression avec kubectl describe node worker-2.
Vérification et diagnostic
Après avoir appliqué les taints et les tolérances, vérifiez que le planificateur se comporte comme prévu. Utilisez les commandes suivantes pour inspecter les taints des nœuds, les tolérances des pods et les échecs de planification.
1. Inspecter les taints des nœuds
kubectl describe node worker-2 | grep Taints
Sortie attendue :
Taints: team=blue:NoExecute
2. Inspecter les tolérances des pods
kubectl describe pod tolerated-pod | grep Tolerations -A5
Sortie attendue :
Tolerations: team=blue:NoExecute op=Exists
La sortie montre la correspondance de tolérance. L'opérateur peut être Equal ou Exists, selon la spécification du pod.
3. Vérifier les événements du pod pour les échecs de planification
Si un pod est bloqué en Pending, inspectez les événements :
kubectl describe pod test-pod | grep -A10 Events
Exemple de sortie :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 10s default-scheduler 0/3 nodes are available: 1 node(s) had untolerated taint {team: blue}, 2 node(s) didn't match node selector.
4. Utiliser des colonnes personnalisées pour un aperçu rapide
Listez les nœuds avec taints :
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
Listez les pods avec tolérances (nécessite jq) :
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, tolerations: .spec.tolerations}'
5. Vérifier les pods existants sur les nœuds tachés
Listez les pods liés à un nœud spécifique :
kubectl get pods --field-selector spec.nodeName=worker-2
Vérifiez que tous les pods ont des tolérances appropriées.
Pièges courants et comment les éviter
Une mauvaise utilisation des taints et des tolérances peut entraîner des échecs de planification ou des évictions non désirées. Voici les erreurs courantes et les stratégies pour les éviter ou s'en remettre.
Piège 1 : Tacher tous les nœuds sans tolérances pour les pods système
Ce qui se passe : Vous appliquez un taint NoSchedule à tous les nœuds travailleurs, peut-être pour les dédier à une charge de travail spécifique. Les pods système dans kube-system (par exemple, kube-proxy, agents CNI) peuvent manquer de tolérances correspondantes et devenir non planifiables, provoquant une instabilité du cluster.
Comment éviter : Avant de tacher un nœud, vérifiez les tolérances des pods système. La plupart des pods système ont des tolérances intégrées pour les taints du plan de contrôle mais pas pour les taints personnalisés. Ajoutez des tolérances aux daemonsets système ou appliquez des taints uniquement à un sous-ensemble de nœuds.
Comment récupérer : Supprimez le taint immédiatement :
kubectl taint nodes <node-name> <key>=<value>:<effect>-
Par exemple :
kubectl taint nodes worker-1 team=blue:NoSchedule-
Puis redémarrez les daemonsets affectés si nécessaire :
kubectl rollout restart daemonset/kube-proxy -n kube-system
Piège 2 : Le taint NoExecute provoque une éviction massive
Ce qui se passe : Appliquer un taint NoExecute sans s'assurer que les pods existants ont des tolérances évince tous les pods non tolérants sur le nœud, perturbant potentiellement les applications.
Comment éviter : Testez d'abord dans un environnement de staging. Utilisez initialement PreferNoSchedule ou NoSchedule. Avant d'appliquer NoExecute, vérifiez que les pods critiques ont des tolérances correspondantes. Envisagez d'utiliser un court tolerationSeconds pour retarder l'éviction et donner aux applications le temps de se replanifier gracieusement.
Comment récupérer : Supprimez le taint :
kubectl taint nodes <node-name> <key>=<value>:NoExecute-
Les pods évincés gérés par des contrôleurs (par exemple, Deployments) seront replanifiés automatiquement. Les pods autonomes peuvent devoir être recréés manuellement.
Piège 3 : Les tolérances ne correspondent pas exactement aux taints
Ce qui se passe : Une tolérance de pod peut avoir une clé, une valeur ou un effet différent du taint de nœud, de sorte que le pod n'est pas planifié.
Comment éviter : Utilisez operator: Exists lorsque vous voulez tolérer n'importe quelle valeur pour une clé, ou assurez une correspondance exacte lors de l'utilisation de Equal. Vérifiez les définitions de taint et de tolérance.
Comment récupérer : Mettez à jour la tolérance du pod pour correspondre au taint. Réappliquez le pod.
Piège 4 : Ignorer les limites de PreferNoSchedule
Ce qui se passe : Vous vous attendez à ce que les pods évitent un nœud avec PreferNoSchedule, mais ils peuvent quand même y être planifiés si aucun autre nœud ne correspond aux autres contraintes.
Comment éviter : Si un évitement strict est requis, utilisez NoSchedule ou NoExecute avec des tolérances pour les pods souhaités.
Piège 5 : Abuser des taints au lieu de l'isolation par espace de noms
Ce qui se passe : Les équipes peuvent utiliser des taints pour isoler les charges de travail, mais cela peut entraîner une fragmentation des nœuds et une sous-utilisation. Les taints ne remplacent pas les quotas d'espace de noms ou les politiques réseau.
Comment éviter : Utilisez les taints avec parcimonie pour le matériel spécial ou les rôles de nœuds. Utilisez les espaces de noms, les quotas de ressources et RBAC pour l'isolation multi-locataires.
Modes de défaillance et récupération
Comprendre les scénarios de défaillance vous aide à réagir rapidement et à minimiser les temps d'arrêt. Chaque mode de défaillance comprend des symptômes et une récupération étape par étape.
Mode de défaillance 1 : Tacher tous les nœuds empêche la planification
Scénario : Vous appliquez un taint NoSchedule à tous les nœuds travailleurs, dans l'intention de les dédier. Les pods système sans tolérances deviennent non planifiables. Les nouveaux pods échouent également à se planifier.
Symptômes : Les nouveaux pods restent en Pending. Les événements montrent 0/3 nodes are available: 3 node(s) had untolerated taint {team: blue}. Les services du cluster se dégradent.
Récupération :
- Supprimez les taints d'au moins un nœud :
kubectl taint nodes worker-1 team=blue:NoSchedule-
kubectl taint nodes worker-2 team=blue:NoSchedule-
- Vérifiez que la planification reprend :
kubectl get pods --all-namespaces
Mode de défaillance 2 : Le taint NoExecute provoque une éviction massive
Scénario : Appliquer NoExecute à un nœud sans s'assurer que les pods critiques ont des tolérances évince tous les pods non tolérants, perturbant les applications.
Symptômes : De nombreux pods affichent le statut Terminating ; les services peuvent tomber en panne.
Récupération :
- Supprimez le taint immédiatement :
kubectl taint nodes worker-2 team=blue:NoExecute-
- Vérifiez l'état des pods :
kubectl get pods --all-namespaces
- Pour les pods gérés par des contrôleurs, ils se replanifieront automatiquement. Pour les pods autonomes, recréez-les.
Mode de défaillance 3 : Non-correspondance des tolérances du pod
Scénario : Un pod a une tolérance qui ne correspond pas exactement au taint, il n'est donc pas planifié sur le nœud souhaité.
Symptômes : Le pod reste Pending ; les événements montrent untolerated taint.
Récupération :
- Corrigez la tolérance dans la spécification du pod. Assurez-vous que la clé, la valeur (si vous utilisez
Equal) et l'effet correspondent exactement. UtilisezExistspour tolérer n'importe quelle valeur pour une clé si approprié. - Réappliquez le pod :
kubectl apply -f corrected-pod.yaml
Mode de défaillance 4 : Éviction par taint des pods système critiques
Scénario : Tacher un nœud avec NoExecute évince les pods système comme kube-proxy ou les agents CNI qui manquent de tolérances pour le taint personnalisé.
Symptômes : Problèmes réseau, le nœud devient NotReady, les composants du cluster fonctionnent mal.
Récupération :
- Supprimez le taint :
kubectl taint nodes worker-2 team=blue:NoExecute-
- Vérifiez les pods système :
kubectl get pods -n kube-system
- Si les pods système ont été évincés et ne sont pas recréés automatiquement, redémarrez le daemonset ou le deployment concerné :
kubectl rollout restart daemonset/kube-proxy -n kube-system
Mode de défaillance 5 : Taint PreferNoSchedule ignoré
Scénario : Des pods sont planifiés sur un nœud avec PreferNoSchedule malgré la préférence.
Symptômes : Des pods s'exécutent sur le nœud taché.
Récupération : Si un évitement strict est requis, changez l'effet en NoSchedule ou NoExecute et ajoutez des tolérances aux pods souhaités.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour la planification, l'application et la révision des taints et des tolérances. Attribuez un responsable à chaque étape. Le responsable est chargé de l'exécution et de la documentation. Les révisions doivent avoir lieu au moins une fois par mois ou chaque fois que la configuration du cluster change.
Phase de planification
- [ ] Responsable : Administrateur de cluster (par exemple, Alex Johnson)
- Identifiez l'objectif : Pourquoi avez-vous besoin de taints ? (par exemple, nœuds dédiés pour les charges de travail GPU, matériel spécial, isolation).
- Déterminez la portée : Quels nœuds seront tachés ? Quelles charges de travail doivent tolérer ?
- Choisissez l'effet :
PreferNoSchedule,NoScheduleouNoExecuteselon les besoins. - Documentez la clé-valeur du taint et l'effet dans un runbook central.
- Assurez-vous que tous les pods système critiques qui pourraient être affectés ont des tolérances appropriées.
Phase de mise en œuvre
- [ ] Responsable : Administrateur de cluster
- Appliquez les taints en utilisant la séquence sûre :
PreferNoSchedule->NoSchedule->NoExecute(si nécessaire). - Utilisez
--overwriteuniquement lors de la modification intentionnelle d'un taint existant. - Après chaque changement de taint, vérifiez les taints des nœuds avec
kubectl describe node. - Déployez des pods de test avec et sans tolérances pour confirmer le comportement de planification.
- Surveillez la planification des pods et la préparation des nœuds.
Phase de vérification
- [ ] Responsable : Ingénieur DevOps (par exemple, Priya Sharma)
- Vérifiez le placement des pods avec
kubectl get pods -o wide. - Inspectez les événements des pods pour les avertissements de planification.
- Vérifiez qu'aucun pod critique n'a été évincé (en particulier pour
NoExecute). - Exécutez des contrôles de santé du cluster.
Maintenance continue
- [ ] Responsable : Chef d'équipe plateforme (par exemple, Marcus Lee)
- Auditez mensuellement les taints des nœuds et les tolérances des pods pour détecter les dérives.
- Passez en revue les taints avant la maintenance des nœuds ou les opérations de mise à l'échelle.
- Tenez la documentation à jour.
- Incluez la configuration des taints et des tolérances dans l'infrastructure en tant que code (par exemple, GitOps) avec contrôle de version.
Plan de rollback
- [ ] Responsable : Ingénieur d'astreinte (rotation)
- Documentez les commandes exactes de suppression de taint :
kubectl taint nodes <node> <key>=<value>:<effect>- - Testez les procédures de rollback en staging.
- En cas d'éviction massive, ayez un plan pour replanifier rapidement les charges de travail (par exemple, mettre à l'échelle les deployments).
Conclusion
Les taints et les tolérances Kubernetes sont des outils essentiels pour contrôler le placement des pods et l'utilisation des nœuds. Ce guide a expliqué leur architecture, fourni un chemin de configuration sûr, démontré des techniques de vérification et décrit les modes de défaillance courants avec des étapes de récupération. À présent, vous devriez avoir une solide compréhension de la mise en œuvre et de la gestion des taints et des tolérances dans vos clusters.
Points clés à retenir :
- Les taints repoussent les pods des nœuds ; les tolérances permettent aux pods sur les nœuds tachés.
- Les trois effets (
PreferNoSchedule,NoSchedule,NoExecute) offrent différents niveaux de rigueur. - Commencez par l'effet le moins perturbateur et augmentez si nécessaire.
- Vérifiez régulièrement la configuration à l'aide de diagnostics et ayez un plan de rollback prêt.
- Les taints et les tolérances ne sont pas des fonctionnalités de sécurité ; combinez-les avec RBAC, les politiques réseau et les quotas.
Expérimentez dans un cluster de test avec les exemples fournis. Documentez les taints et les tolérances dans le cadre de la configuration du cluster et intégrez-les dans les flux de travail GitOps. Continuez à apprendre sur les fonctionnalités de planification avancées telles que l'affinité de nœuds, l'affinité/anti-affinité des pods et les classes de priorité pour construire une stratégie de planification complète. Avec une planification minutieuse et une discipline opérationnelle, vous pouvez tirer parti des taints et des tolérances pour un placement de charge de travail efficace et prévisible.
Pour approfondir, consultez la documentation officielle de Kubernetes sur les taints et les tolérances.