Introduction
Les taints et tolérances Kubernetes sont le mécanisme principal pour contrôler quels pods peuvent être ordonnancés sur quels nœuds. Un taint sur un nœud repousse les pods qui ne le tolèrent pas, tandis qu'une tolérance sur un pod lui permet d'être ordonnancé sur des nœuds avec des taints correspondants. Cet article fournit un guide pratique et tenant compte des versions pour la mise à niveau et la migration des taints et tolérances dans un cluster Kubernetes en cours d'exécution. Que vous passiez à une nouvelle version de Kubernetes, restructuriez vos pools de nœuds ou appliquiez de nouvelles politiques d'ordonnancement, les étapes ci-dessous vous aident à observer, planifier, exécuter, vérifier et revenir en arrière avec un minimum de perturbations.
Nous nous concentrons sur des flux de travail opérationnels réels : vérifier votre version actuelle et la configuration des taints, planifier une migration qui limite le rayon d'impact, appliquer les changements de manière contrôlée, valider que l'ordonnancement se comporte comme prévu et récupérer en cas de problème. Chaque section comprend des commandes concrètes, des sorties attendues, des signaux d'échec et des décisions de récupération. L'objectif est la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact, utiliser des valeurs génériques plutôt que des secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint.
Inventaire des versions et de l'environnement
Avant de toucher à un taint ou une tolérance, vous avez besoin d'un inventaire complet de la version de votre cluster, des taints des nœuds, des tolérances des pods et de la topologie de déploiement pertinente. Cela établit une base de référence et vous aide à anticiper les problèmes de compatibilité. Commencez par collecter la version du serveur Kubernetes et vérifiez les dépréciations d'API qui concernent les taints et tolérances.
Vérifier les versions du cluster et des nœuds
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.24.3
Server Version: v1.23.8
Les taints et tolérances sont stables depuis Kubernetes v1.6, mais les versions plus récentes peuvent déprécier certains effets de taint ou en ajouter de nouveaux. Par exemple, les taints node.kubernetes.io/not-ready et node.kubernetes.io/unreachable existent depuis les premières versions, mais le taint node.kubernetes.io/unschedulable est automatiquement ajouté par le planificateur. Vérifiez toujours que votre version cible prend en charge les effets de taint que vous prévoyez d'utiliser (NoSchedule, PreferNoSchedule ou NoExecute).
Lister les taints actuels des nœuds
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
Exemple de sortie :
NAME TAINTS
node-1 [map[effect:NoSchedule key:dedicated value:database]]
node-2 <none>
node-3 [map[effect:PreferNoSchedule key:gpu value:true]]
Cela montre quels nœuds ont des taints et quels sont leur clé, valeur et effet. Notez que la sortie n'est pas toujours facile à lire ; pour une vue plus propre, utilisez kubectl describe nodes et recherchez le champ Taints.
Lister les tolérances des pods existants
Pour comprendre quels pods tolèrent déjà quels taints, inspectez leur YAML ou utilisez une requête JSONPath :
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{"\t"}{.spec.tolerations}{"\n"}{end}'
Cela peut produire quelque chose comme :
default/nginx-deployment-7d4b8d6c9-abcde [map[key:dedicated value:database effect:NoSchedule]]
kube-system/coredns-558bd4d5db-xyz12 <no tolerations>
Un pod sans tolérance ne peut pas être ordonnancé sur un nœud avec un taint NoSchedule. Si vous introduisez un nouveau taint, vous devez vous assurer que tous les pods qui doivent s'exécuter sur ce nœud ont une tolérance correspondante.
Vérifier les conditions et événements des nœuds
Utilisez kubectl describe node <node-name> pour voir les conditions et les événements récents qui peuvent affecter l'ordonnancement. Pour un pod problématique, utilisez :
kubectl describe pod <pod-name> -n <namespace>
Recherchez des événements comme :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 10s default-scheduler 0/3 nodes are available: 1 node(s) had taint {dedicated: database}, that the pod didn't tolerate, 2 Insufficient cpu.
Cela vous indique exactement quel taint bloque l'ordonnancement. Vérifiez également les journaux du planificateur ou du kube-controller-manager si vous soupçonnez un problème de propagation des taints.
Liste de contrôle préalable
kubectlinstallé et configuré avec les autorisations RBAC appropriées (get, list, patch sur les nœuds et pods).jqpour traiter les sorties JSON (facultatif mais utile).- Un espace de noms de test ou un cluster où vous pouvez valider les changements avant la production.
- Sauvegarde des configurations actuelles des nœuds et des pods, surtout si vous les gérez via GitOps.
Petit test local
Avant de faire un changement à l'échelle du cluster, testez dans un environnement local (par exemple, kind, minikube ou un espace de noms de test dédié). Créez un seul nœud avec un taint et un pod avec une tolérance pour confirmer le comportement :
# Créer un cluster à un seul nœud avec kind
kind create cluster --config kind-config.yaml
# où kind-config.yaml définit un nœud control-plane
Ensuite, appliquez un taint et un pod :
kubectl taint nodes kind-control-plane dedicated=database:NoSchedule
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "database"
effect: "NoSchedule"
containers:
- name: nginx
image: nginx
EOF
Vérifiez que le pod est ordonnancé :
kubectl get pod test-pod
Si le pod est Pending, exécutez kubectl describe pod test-pod pour voir l'erreur de taint.
Chemin de configuration sûr
Une fois que vous avez un inventaire, planifiez votre migration de taints avec un chemin sûr qui minimise l'impact. Le principe de base : changez une chose à la fois, observez et ayez un plan de retour en arrière. Cette section décrit une procédure étape par étape pour mettre à niveau les taints et tolérances, y compris les considérations de compatibilité de version.
Étape 1 : Identifier l'ensemble de taints cible
Décidez quels taints vous avez besoin sur quels nœuds. Par exemple, vous pouvez vouloir dédier un ensemble de nœuds à une charge de travail spécifique en ajoutant un taint workload=ml:NoSchedule. Ou vous pouvez vouloir supprimer un taint obsolète. Documentez l'état souhaité pour chaque groupe de nœuds.
Étape 2 : Vérifier la compatibilité de version
Si vous mettez également à niveau Kubernetes, assurez-vous que le comportement des taints est inchangé. Consultez les notes de version de Kubernetes pour toute dépréciation liée aux taints. Par exemple, les taints avec effet NoExecute peuvent évincer les pods déjà en cours d'exécution qui ne les tolèrent pas ; si vous ajoutez un tel taint, soyez prêt à l'éviction.
Étape 3 : Ajouter les tolérances avant les taints
L'ordre le plus sûr est d'ajouter des tolérances aux pods qui doivent rester sur un nœud avant d'ajouter le taint à ce nœud. Cela évite une fenêtre où les pods sont non ordonnançables ou évincés. Pour un déploiement, mettez à jour le modèle de pod :
apiVersion: apps/v1
kind: Deployment
metadata:
name: ml-workload
spec:
replicas: 2
selector:
matchLabels:
app: ml-workload
template:
metadata:
labels:
app: ml-workload
spec:
tolerations:
- key: "workload"
operator: "Equal"
value: "ml"
effect: "NoSchedule"
containers:
- name: trainer
image: my-ml-image:latest
Appliquez le changement et attendez la fin du déploiement :
kubectl apply -f deployment.yaml
kubectl rollout status deployment/ml-workload
Sortie attendue :
deployment "ml-workload" successfully rolled out
Étape 4 : Ajouter les taints aux nœuds de manière incrémentale
Commencez par un nœud dans un pool de nœuds (si vous avez plusieurs nœuds) pour limiter le rayon d'impact. Utilisez kubectl taint pour ajouter le taint :
kubectl taint nodes node-1 workload=ml:NoSchedule
Vérifiez que le taint a été ajouté :
kubectl get node node-1 -o jsonpath='{.spec.taints}'
Sortie attendue :
[{"effect":"NoSchedule","key":"workload","value":"ml"}]
Maintenant, vérifiez que vos pods prévus sont toujours en cours d'exécution et que les nouveaux pods avec tolérances peuvent être ordonnancés. Utilisez kubectl get pods -o wide pour voir les affectations de nœuds.
Étape 5 : Surveiller l'ordonnancement
Si vous avez ajouté un taint NoExecute, Kubernetes évincera immédiatement les pods non tolérants. Pour éviter des évictions surprises, vous pouvez d'abord ajouter le taint avec NoSchedule, puis passer à NoExecute après avoir confirmé qu'aucun pod critique n'est affecté. Pour changer un taint existant, vous devez le supprimer et le réajouter :
kubectl taint nodes node-1 workload=ml:NoSchedule-
kubectl taint nodes node-1 workload=ml:NoExecute
C'est une séquence destructive, donc soyez prudent. Ayez toujours une sauvegarde du taint original si vous devez revenir en arrière.
Étape 6 : Valider avec des vérifications en lecture seule
Avant de déclarer le succès, exécutez une série de commandes de diagnostic (couvertes dans la section suivante) pour confirmer que seuls les pods prévus sont ordonnancés sur les nœuds taints et qu'aucune éviction involontaire n'a eu lieu.
Petit test local pour une configuration sûre
Dans votre cluster local, simulez une migration : créez deux nœuds, ajoutez un taint à l'un, déployez un pod sans tolérance et un pod avec tolérance, et observez l'ordonnancement. Utilisez kubectl cordon et kubectl drain si vous devez déplacer des pods avant d'ajouter des taints. Par exemple, pour drainer un nœud avant d'ajouter un taint :
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
Ensuite, ajoutez le taint et décordonez :
kubectl taint nodes node-1 dedicated=test:NoSchedule
kubectl uncordon node-1
Cela garantit qu'aucun pod existant n'est bloqué sur le nœud lorsque le taint prend effet.
Vérification et diagnostic
Après avoir appliqué des taints ou des tolérances, vous devez vérifier que le comportement d'ordonnancement correspond à vos attentes. Cette section fournit un ensemble complet de commandes et de vérifications pour diagnostiquer les problèmes.
Confirmer l'application des taints
Listez tous les taints des nœuds dans un format lisible :
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, taints: .spec.taints}'
Exemple de sortie :
{
"name": "node-1",
"taints": [
{
"effect": "NoSchedule",
"key": "workload",
"value": "ml"
}
]
}
{
"name": "node-2",
"taints": null
}
Vérifier l'ordonnancement des pods
Utilisez kubectl get pods -o wide pour voir sur quel nœud chaque pod se trouve. Pour un pod spécifique, décrivez-le pour voir les événements :
kubectl describe pod <pod-name>
Recherchez la section Events. Un événement d'ordonnancement réussi montre :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5s default-scheduler Successfully assigned default/ml-workload-abcde to node-1
S'il n'est pas ordonnancé, vous verrez un événement FailedScheduling avec la raison. Par exemple :
Warning FailedScheduling 2s default-scheduler 0/3 nodes are available: 1 node(s) had taint {workload: ml}, that the pod didn't tolerate, 2 Insufficient memory.
Inspecter les tolérances des pods en cours d'exécution
Pour vérifier qu'un pod a la bonne tolérance, utilisez :
kubectl get pod ml-workload-abcde -o jsonpath='{.spec.tolerations}'
Sortie attendue :
[{"effect":"NoSchedule","key":"workload","operator":"Equal","value":"ml"}]
Tester avec un essai à sec
Vous pouvez utiliser kubectl apply --dry-run=server pour valider les modifications de manifeste sans les appliquer réellement :
kubectl apply -f deployment.yaml --dry-run=server
Cela détecte les erreurs de syntaxe ou les formats de tolérance invalides.
Utiliser les étiquettes de nœuds avec les taints
Les taints servent à repousser les pods ; les étiquettes de nœuds servent à attirer les pods via des sélecteurs de nœuds ou des affinités. Pour garantir que les pods atterrissent sur les bons nœuds, combinez les taints avec des étiquettes de nœuds et des sélecteurs de nœuds de pods. Par exemple, étiquetez le nœud :
kubectl label nodes node-1 workload=ml
Ensuite, dans la spécification du pod, ajoutez :
nodeSelector:
workload: ml
Cela rend l'ordonnancement plus déterministe.
Vérifier les évictions
Si vous avez utilisé NoExecute, surveillez les pods évincés :
kubectl get events --all-namespaces --field-selector reason=Evicted
Exemple de sortie :
NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE
default 1m Warning Evicted pod/old-pod The pod was evicted due to a taint
Si vous voyez des évictions inattendues, supprimez immédiatement le taint ou ajoutez des tolérances aux pods affectés.
Modes de défaillance et récupération
Même avec une planification minutieuse, les changements de taints peuvent mal tourner. Cette section décrit les modes de défaillance courants et comment s'en remettre.
Mode de défaillance 1 : Pod bloqué en Pending à cause d'un taint
Symptôme : Un pod reste Pending avec un événement FailedScheduling indiquant une non-correspondance de taint.
Diagnostic : Décrivez le pod et vérifiez les événements. Vérifiez également les taints du nœud et les tolérances du pod.
Récupération :
- Si le pod doit tolérer le taint, ajoutez la tolérance appropriée à la spécification du pod et réappliquez.
- Si le taint a été ajouté par erreur, supprimez-le du nœud :
kubectl taint nodes node-1 workload=ml:NoSchedule-
Notez le signe moins à la fin, qui supprime le taint.
- Si le pod fait partie d'un contrôleur (Deployment, StatefulSet), mettez à jour le modèle et déployez.
Mode de défaillance 2 : Éviction involontaire de pods critiques
Symptôme : Après avoir ajouté un taint NoExecute, des pods système critiques (par exemple, kube-proxy, DNS) sont évincés.
Diagnostic : Vérifiez kubectl get pods -n kube-system et les événements. Les pods système peuvent manquer de tolérances pour les taints personnalisés.
Récupération :
- Supprimez immédiatement le taint :
kubectl taint nodes node-1 workload=ml:NoExecute-
- Ajoutez les tolérances nécessaires aux pods critiques ou assurez-vous qu'ils sont dans un daemonset qui tolère tous les taints.
- Alternativement, utilisez l'effet
PreferNoSchedulepour éviter l'éviction dure.
Mode de défaillance 3 : La suppression du taint ne fonctionne pas
Symptôme : Vous exécutez kubectl taint nodes node-1 key=value:Effect-, mais le taint reste.
Diagnostic : Vérifiez que la clé et la valeur du taint correspondent exactement à ce qui est sur le nœud. Les taints sont une correspondance exacte pour la clé et la valeur. Si vous omettez la valeur pour un taint avec opérateur Equal, cela ne correspondra pas.
Récupération :
- Obtenez le taint exact :
kubectl get node node-1 -o json | jq '.spec.taints'
- Supprimez avec la clé, la valeur et l'effet exacts :
kubectl taint nodes node-1 dedicated=database:NoSchedule-
Mode de défaillance 4 : Incompatibilité de version
Symptôme : Après une mise à niveau de Kubernetes, les taints se comportent différemment ou des erreurs se produisent.
Diagnostic : Vérifiez les versions d'API et les journaux. Certaines fonctionnalités de taint peuvent avoir changé.
Récupération :
- Revenez en arrière sur la mise à niveau de Kubernetes si possible.
- Ajustez les taints et tolérances pour correspondre aux attentes de la nouvelle version. Par exemple, dans les versions plus récentes, le taint
node.kubernetes.io/not-readya un temps de tolérance par défaut différent pour les pods. - Consultez le journal des modifications de Kubernetes pour les changements cassants.
Procédure générale de retour en arrière
Gardez toujours un enregistrement des taints et tolérances d'origine. Si vous utilisez GitOps, annulez le commit. Pour les changements manuels, documentez chaque commande et son inverse. Par exemple, pour annuler l'ajout d'un taint, exécutez la commande de suppression. Pour annuler l'ajout d'une tolérance, modifiez la spécification du pod et supprimez la tolérance.
Si un changement provoque une perturbation significative, vous pouvez également cordonner et drainer les nœuds affectés, supprimer le taint, puis décordonner.
kubectl cordon node-1
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
kubectl taint nodes node-1 workload=ml:NoSchedule-
kubectl uncordon node-1
Cela force tous les pods à quitter le nœud, supprime le taint et le remet en rotation.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour chaque mise à niveau ou migration de taints et tolérances. Elle résume les étapes clés et inclut des commandes de vérification concrètes.
| Étape | Action | Commande / Vérification | Résultat attendu |
|---|---|---|---|
| 1 | Enregistrer la version actuelle du cluster et les taints des nœuds | kubectl version --short et kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints | Version listée, taints visibles |
| 2 | Identifier les taints et tolérances cibles | Documenter l'état souhaité | Liste claire des changements |
| 3 | Ajouter les tolérances aux pods avant d'ajouter les taints | Modifier la spécification du Deployment ou du Pod, appliquer, kubectl rollout status | Déploiement réussi |
| 4 | Ajouter le taint à un seul nœud de test | kubectl taint nodes <node> key=value:NoSchedule | Le taint apparaît dans la spécification du nœud |
| 5 | Vérifier l'ordonnancement des pods sur le nœud de test | kubectl get pods -o wide et kubectl describe pod | Pod ordonnancé sur le nœud prévu |
| 6 | Surveiller les évictions | kubectl get events --all-namespaces --field-selector reason=Evicted | Aucune éviction inattendue |
| 7 | Déployer sur les nœuds restants de manière incrémentale | Répéter l'ajout de taint pour chaque nœud, en vérifiant entre chaque | Tous les nœuds taints, aucun problème |
| 8 | Mettre à jour la documentation et les runbooks | Enregistrer les commandes et sorties réelles | Documentation à jour |
| 9 | Planifier une validation périodique | par exemple, script hebdomadaire pour comparer les taints des nœuds et les tolérances des pods | Dérive détectée tôt |
Exemple de script de validation
Vous pouvez créer un script simple pour valider qu'un ensemble de nœuds ont les taints attendus et que les pods ont des tolérances correspondantes. Voici un extrait utilisant bash et kubectl :
#!/bin/bash
# Vérifier que tous les nœuds avec l'étiquette workload=ml ont le taint workload=ml:NoSchedule
for node in $(kubectl get nodes -l workload=ml -o name); do
taints=$(kubectl get $node -o jsonpath='{.spec.taints}')
if [[ "$taints" != *"workload=ml:NoSchedule"* ]]; then
echo "ERREUR : $node manque le taint"
else
echo "OK : $node a le bon taint"
fi
done
# Vérifier que tout pod avec une tolérance pour workload=ml est en état Running
for pod in $(kubectl get pods -A -o json | jq -r '.items[] | select(.spec.tolerations[]?.key=="workload") | .metadata.namespace+"/"+.metadata.name'); do
ns=${pod%/*}
name=${pod#*/}
status=$(kubectl get pod $name -n $ns -o jsonpath='{.status.phase}')
if [[ "$status" != "Running" ]]; then
echo "AVERTISSEMENT : $pod dans $ns est $status"
else
echo "OK : $pod en cours d'exécution"
fi
done
Ce script fournit une vérification automatisée rapide après les changements.
Conclusion
Les taints et tolérances Kubernetes sont puissants mais nécessitent une gestion prudente lors des mises à niveau et des migrations. En suivant l'approche axée sur les versions et l'observation d'abord décrite dans cet article, vous pouvez minimiser les risques et vous assurer que les politiques d'ordonnancement de votre cluster restent correctes et efficaces.
Points clés à retenir :
- Inventoriez toujours vos taints, tolérances et version de cluster actuels avant de faire des changements.
- Ajoutez des tolérances aux pods avant d'ajouter des taints aux nœuds pour éviter les échecs d'ordonnancement.
- Déployez les changements de manière incrémentale, en commençant par un nœud de test.
- Utilisez
kubectl describeet les événements pour diagnostiquer les problèmes d'ordonnancement. - Ayez un plan de retour en arrière clair et documentez chaque commande.
- Validez avec des scripts et des vérifications périodiques pour détecter la dérive.
Comme prochaine étape, choisissez une vérification à faible risque pour votre propre cluster : enregistrez les taints actuels sur un nœud, ajoutez une tolérance à un pod de test et confirmez qu'il s'ordonnance comme prévu. Ensuite, examinez les dépendances telles que les étiquettes de nœuds, les sélecteurs de nœuds et l'anti-affinité des pods, car elles interagissent avec les taints et tolérances.
Un flux de travail technique fiable rend les échecs visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision.