Kubernetes taint

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
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 nodeSelector quand un contrôle précis du placement est recherché.
  • Éviter les tolerations universelles (operator: Exists sans 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-

Voir aussi