Kubernetes taint
| Fiche express | |
|---|---|
| Type | Restriction de placement appliquée à un nœud |
| Contrepartie côté Pod | Toleration |
| Effects | NoSchedule · PreferNoSchedule · NoExecute
|
| Voir aussi | Kubernetes scheduling · Kubernetes daemonSets |
Un taint est une restriction appliquée à un nœud pour empêcher le scheduling de Pods dessus, sauf si ces Pods possèdent la toleration correspondante. L'analogie usuelle : un taint est une pancarte « accès réservé » sur un nœud — seuls les Pods porteurs du bon badge (la toleration) peuvent s'y installer. C'est le mécanisme complémentaire du nodeSelector décrit dans Kubernetes scheduling : là où le sélecteur attire un Pod vers un nœud, le taint repousse les Pods d'un nœud.
Anatomie d'un taint
spec:
taints:
- key: node-role.kubernetes.io/control-plane
value: "" # optionnel
effect: NoSchedule # obligatoire
| Composant | Description | Obligatoire |
|---|---|---|
| key | Identifiant du taint (ex. node-role.kubernetes.io/control-plane) |
Oui |
| value | Valeur associée (ex. true, gpu) |
Non |
| effect | Comportement de restriction appliqué | Oui |
Les trois effects
| Effect | Comportement | Cas d'usage typique |
|---|---|---|
| NoSchedule | Bloque les nouveaux Pods ; les Pods déjà en place restent | Control-plane par défaut, maintenance planifiée |
| PreferNoSchedule | Évite le nœud si possible, mais l'autorise si nécessaire | Préférence souple, sans garantie |
| NoExecute | Bloque les nouveaux Pods et évacue les Pods déjà en place | Maintenance d'urgence, mise en quarantaine d'un nœud |
Commandes essentielles
Consulter les taints
# Lister les taints de tous les nœuds
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
# Taints d'un nœud spécifique
kubectl describe node <nom-du-noeud> | grep -A 3 Taints
Ajouter, retirer, modifier
# Syntaxe générale
kubectl taint node <nom-du-noeud> <cle>=<valeur>:<effect>
# Exemples
kubectl taint node worker-01 dedicated=gpu:NoSchedule
kubectl taint node worker-02 maintenance=true:NoExecute
kubectl taint node worker-03 env=prod:PreferNoSchedule
# Sans valeur (juste la clé)
kubectl taint node worker-04 special-hardware:NoSchedule
# Retirer un taint (notez le '-' final)
kubectl taint node worker-01 dedicated:NoSchedule-
# Retirer TOUS les taints portant une clé donnée
kubectl taint node worker-01 dedicated-
# Modifier un taint existant
kubectl taint node worker-01 dedicated=gpu:NoExecute --overwrite
Tolerations côté Pod
Pour qu'un Pod puisse s'exécuter sur un nœud taintée, il doit porter une toleration correspondante.
# Toleration exacte : clé + valeur + effect identiques
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
# Toleration par existence : tolère la clé quelle que soit sa valeur
tolerations:
- key: "dedicated"
operator: "Exists"
effect: "NoSchedule"
# Toleration universelle : tolère TOUS les taints — à réserver à des cas très particuliers
tolerations:
- operator: "Exists"
# Toleration temporisée (NoExecute uniquement) : le Pod reste 300s après
# l'application du taint, puis est évacué
tolerations:
- key: "maintenance"
operator: "Equal"
value: "true"
effect: "NoExecute"
tolerationSeconds: 300
Taints standards
Un certain nombre de taints sont posés par défaut ou automatiquement par le node controller :
| Taint | Effect | Origine |
|---|---|---|
node-role.kubernetes.io/control-plane |
NoSchedule | Posé par défaut sur les nœuds de control-plane |
node-role.kubernetes.io/master |
NoSchedule | Ancien nom, versions de Kubernetes antérieures à 1.24 |
node.kubernetes.io/not-ready |
NoExecute | Automatique, nœud non prêt |
node.kubernetes.io/unreachable |
NoExecute | Automatique, nœud injoignable |
node.kubernetes.io/disk-pressure |
NoSchedule | Automatique, disque saturé |
node.kubernetes.io/memory-pressure |
NoSchedule | Automatique, mémoire insuffisante |
node.kubernetes.io/pid-pressure |
NoSchedule | Automatique, nombre de PID insuffisant |
node.kubernetes.io/network-unavailable |
NoSchedule | Automatique, réseau indisponible |
node.kubernetes.io/unschedulable |
NoSchedule | Automatique, nœud marqué non-schedulable |
Ces taints automatiques sont gérés par le node controller et ne doivent pas être modifiés manuellement. Par défaut, un délai de 300 secondes est appliqué avant évacuation pour not-ready et unreachable (à vérifier selon la version du cluster, ce délai peut être ajusté via des tolerations spécifiques).
Cas d'usage pratiques
Nœud avec GPU dédié
kubectl taint node gpu-worker-01 nvidia.com/gpu=true:NoSchedule
spec:
tolerations:
- key: nvidia.com/gpu
operator: Equal
value: "true"
effect: NoSchedule
nodeSelector:
accelerator: nvidia-tesla-v100
Le taint réserve le nœud aux Pods qui le tolèrent explicitement ; le nodeSelector complémentaire garantit en plus que ces Pods choisissent bien ce type de nœud (le taint seul ne fait qu'exclure, il n'attire rien).
Maintenance planifiée puis levée
# Empêcher les nouveaux Pods, garder les existants
kubectl taint node worker-05 maintenance=scheduled:NoSchedule
# Après intervention
kubectl taint node worker-05 maintenance:NoSchedule-
Maintenance d'urgence
# Évacue immédiatement tous les Pods, qui seront replanifiés ailleurs
kubectl taint node worker-06 maintenance=emergency:NoExecute
Réservation d'un pool de nœuds de production
kubectl taint node prod-worker-01 env=production:NoSchedule
kubectl taint node prod-worker-02 env=production:NoSchedule
spec:
tolerations:
- key: env
operator: Equal
value: production
effect: NoSchedule
nodeSelector:
environment: production
Rendre le control-plane schedulable (petit cluster / environnement de développement)
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
# Vérification : la sortie doit indiquer "Taints: <none>"
kubectl describe nodes | grep Taints
À réserver aux clusters mono/bi-nœud de développement — en production, ce taint protège le control-plane des workloads applicatifs et doit être conservé.
Taint vs label vs nodeSelector
| Concept | Fonction | Direction | Exemple |
|---|---|---|---|
| Taint | Repousse les Pods | Nœud → Pod | « ce nœud refuse les Pods, sauf toleration » |
| Toleration | Accepte un taint | Pod → Nœud | « ce Pod accepte d'aller sur ce nœud » |
| Label | Étiquette descriptive | Nœud | gpu=true
|
| nodeSelector | Sélectionne un nœud | Pod → Nœud | « ce Pod veut un nœud avec gpu=true »
|
Combiner taint et nodeSelector est la pratique la plus robuste pour un contrôle de placement précis : le taint bloque les Pods non autorisés, le label/sélecteur identifie et attire les bons Pods vers le bon nœud. Voir aussi Kubernetes scheduling pour nodeSelector et nodeName.
DaemonSets et taints
Les DaemonSets doivent souvent tourner partout, y compris sur des nœuds normalement taintés (control-plane, nœuds non prêts) — on leur ajoute alors des tolerations explicites :
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: agent-monitoring
spec:
template:
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node.kubernetes.io/not-ready
operator: Exists
effect: NoExecute
containers:
- name: agent
image: agent-monitoring:latest
Dépannage
Pod bloqué en Pending
kubectl describe pod <nom-du-pod>
Chercher dans les events un message du type :
0/3 nodes are available: 3 node(s) had taint {key: value}, that the pod didn't tolerate
La solution consiste à ajouter au Pod la toleration correspondante — ou, si la restriction ne se justifie plus, à retirer le taint du nœud.
Comparer manuellement taints et tolerations
# Taints du nœud
kubectl describe node worker-01 | grep Taints
# Tolerations du Pod
kubectl get pod <nom-du-pod> -o yaml | grep -A 10 tolerations
Lister les Pods tolérant un taint donné
kubectl get pods -A -o json | \
jq -r '.items[] | select(.spec.tolerations[]? |
select(.key=="dedicated" and .value=="gpu")) |
.metadata.name'
Scripts utiles
Audit des taints présents sur l'ensemble du cluster :
#!/bin/bash
echo "=== AUDIT TAINTS ==="
for node in $(kubectl get nodes -o name | cut -d'/' -f2); do
echo "Node: $node"
kubectl describe node "$node" | grep -A 3 "Taints:"
echo "---"
done
Retirer le taint control-plane sur tous les nœuds concernés :
#!/bin/bash
for node in $(kubectl get nodes -l node-role.kubernetes.io/control-plane=true -o name | cut -d'/' -f2); do
echo "Removing taint from $node"
kubectl taint node "$node" node-role.kubernetes.io/control-plane- 2>/dev/null || echo "No taint found"
done
Appliquer un taint à l'ensemble des workers (hors control-plane) :
#!/bin/bash
TAINT_KEY="environment"
TAINT_VALUE="production"
EFFECT="NoSchedule"
for node in $(kubectl get nodes -l '!node-role.kubernetes.io/control-plane' -o name | cut -d'/' -f2); do
echo "Adding taint to $node"
kubectl taint node "$node" ${TAINT_KEY}=${TAINT_VALUE}:${EFFECT}
done
Bonnes pratiques
- Utiliser les taints pour la ségrégation des workloads (isolation d'un pool de nœuds), pas pour du simple placement — c'est le rôle du
nodeSelector/de l'affinité. - Préférer des clés descriptives et namespacées, par exemple
monentreprise.example/dedicated=gpu, pour éviter toute collision avec les taints standards. - Documenter les taints personnalisés (ConfigMap, wiki interne) pour que leur intention reste claire dans le temps.
- Combiner systématiquement taint et
nodeSelectorquand un contrôle précis du placement est recherché. - Éviter les tolerations universelles (
operator: Existssans clé) en production : elles annulent l'effet de tous les taints du cluster pour le Pod concerné. - Tester une toleration en environnement de recette avant de l'appliquer en production.
- Conserver le taint du control-plane en production ; ne le retirer qu'en développement ou sur un cluster mono/bi-nœud.
Référence rapide
# VOIR
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
kubectl describe node <nom-du-noeud> | grep Taints
# AJOUTER
kubectl taint node <nom-du-noeud> <cle>=<valeur>:<effect>
# RETIRER (notez le '-' final)
kubectl taint node <nom-du-noeud> <cle>:<effect>-
# MODIFIER
kubectl taint node <nom-du-noeud> <cle>=<valeur>:<effect> --overwrite
# RETIRER LE TAINT CONTROL-PLANE SUR TOUS LES NŒUDS
kubectl taint nodes --all node-role.kubernetes.io/control-plane-