## 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

- kubectl installé et configuré avec les autorisations RBAC appropriées (get, list, patch sur les nœuds et pods).

- jq pour 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.

<style>
.eno-quiz-widget{margin:2rem 0;padding:1.5rem;border-radius:12px;background:var(--eno-surface-lowest,#f7f7f8);border:1px solid var(--eno-border-soft,#e2e2e6);font-family:var(--eno-font-body,Inter,sans-serif)}
.eno-quiz-widget .eno-quiz-kicker{font-family:var(--eno-font-label,"JetBrains Mono",monospace);font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--eno-text-muted,#5f5f68);margin:0 0 .5rem}
.eno-quiz-widget .eno-quiz-question{font-family:var(--eno-font-heading,"Hanken Grotesk",sans-serif);font-size:1.0625rem;font-weight:600;margin:0 0 1rem;color:var(--eno-text-strong,#1a1a1f)}
.eno-quiz-widget .eno-quiz-options{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.eno-quiz-widget .eno-quiz-option{display:block;width:100%;min-height:44px;text-align:left;padding:.625rem .875rem;border-radius:8px;border:1.5px solid var(--eno-border-soft,#e2e2e6);background:#fff;font-size:.9375rem;cursor:pointer;transition:border-color var(--eno-motion-base,180ms ease-out),background var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-option:hover{border-color:var(--eno-primary,#0059bb)}
.eno-quiz-widget .eno-quiz-option:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-option[aria-pressed="true"]{border-color:var(--eno-primary,#0059bb);background:rgb(0 89 187 / 0.06)}
.eno-quiz-widget .eno-quiz-option[data-correct="true"].eno-quiz-revealed{border-color:var(--eno-success,#17803a);background:rgb(23 128 58 / 0.08)}
.eno-quiz-widget .eno-quiz-option[data-correct="false"].eno-quiz-revealed.eno-quiz-was-selected{border-color:var(--eno-error,#ba1a1a);background:var(--eno-error-soft,#ffdad6)}
.eno-quiz-widget .eno-quiz-option-icon{display:inline-block;width:1.1em;margin-right:.4em;font-weight:700}
.eno-quiz-widget .eno-quiz-submit{margin-top:1rem;min-height:44px;padding:.5rem 1.25rem;border-radius:8px;border:none;background:var(--eno-primary,#0059bb);color:#fff;font-weight:600;font-size:.9375rem;cursor:pointer;transition:opacity var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-submit:disabled{opacity:.5;cursor:not-allowed}
.eno-quiz-widget .eno-quiz-submit:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-explanation{margin-top:1rem;padding:.875rem 1rem;border-radius:8px;font-size:.9375rem;line-height:1.5;display:none}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-visible{display:block}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-correct{background:rgb(23 128 58 / 0.08);color:var(--eno-success,#17803a)}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-incorrect{background:var(--eno-error-soft,#ffdad6);color:var(--eno-error,#ba1a1a)}
@media (prefers-reduced-motion: reduce){.eno-quiz-widget *{transition:none!important}}
</style><div class="eno-quiz-widget" role="group" aria-label="Question rapide">
Question rapide 1 sur 2

Quel est l'effet d'un taint `NoExecute` sur les pods qui sont déjà en cours d'exécution sur le nœud et qui ne le tolèrent pas ?

- Ils sont expulsés immédiatement.
- Ils restent liés pour toujours.
- Ils restent liés pendant une durée déterminée.
- Ils ne sont pas expulsés.

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">Les pods qui ne tolèrent pas un taint `NoExecute` sont expulsés immédiatement du nœud.</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.eno-quiz-widget:not([data-eno-quiz-bound])').forEach(function (widget) {
    widget.setAttribute('data-eno-quiz-bound', '1');
    var options = Array.prototype.slice.call(widget.querySelectorAll('.eno-quiz-option'));
    var submitBtn = widget.querySelector('.eno-quiz-submit');
    var explanation = widget.querySelector('.eno-quiz-explanation');
    var selected = null;
    options.forEach(function (opt) {
      opt.addEventListener('click', function () {
        if (widget.hasAttribute('data-eno-quiz-answered')) return;
        options.forEach(function (o) { o.setAttribute('aria-pressed', 'false'); });
        opt.setAttribute('aria-pressed', 'true');
        selected = opt;
        submitBtn.disabled = false;
      });
    });
    submitBtn.addEventListener('click', function () {
      if (!selected || widget.hasAttribute('data-eno-quiz-answered')) return;
      widget.setAttribute('data-eno-quiz-answered', '1');
      submitBtn.disabled = true;
      var correct = selected.getAttribute('data-correct') === 'true';
      options.forEach(function (o) {
        o.classList.add('eno-quiz-revealed');
        if (o === selected) o.classList.add('eno-quiz-was-selected');
        var icon = o.querySelector('.eno-quiz-option-icon');
        if (o.getAttribute('data-correct') === 'true') icon.textContent = '\u2713';
        else if (o === selected) icon.textContent = '\u2717';
      });
      explanation.classList.add('eno-quiz-visible', correct ? 'eno-quiz-correct' : 'eno-quiz-incorrect');
    });
  });
});
</script>

## 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.

<style>
.eno-quiz-widget{margin:2rem 0;padding:1.5rem;border-radius:12px;background:var(--eno-surface-lowest,#f7f7f8);border:1px solid var(--eno-border-soft,#e2e2e6);font-family:var(--eno-font-body,Inter,sans-serif)}
.eno-quiz-widget .eno-quiz-kicker{font-family:var(--eno-font-label,"JetBrains Mono",monospace);font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--eno-text-muted,#5f5f68);margin:0 0 .5rem}
.eno-quiz-widget .eno-quiz-question{font-family:var(--eno-font-heading,"Hanken Grotesk",sans-serif);font-size:1.0625rem;font-weight:600;margin:0 0 1rem;color:var(--eno-text-strong,#1a1a1f)}
.eno-quiz-widget .eno-quiz-options{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.eno-quiz-widget .eno-quiz-option{display:block;width:100%;min-height:44px;text-align:left;padding:.625rem .875rem;border-radius:8px;border:1.5px solid var(--eno-border-soft,#e2e2e6);background:#fff;font-size:.9375rem;cursor:pointer;transition:border-color var(--eno-motion-base,180ms ease-out),background var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-option:hover{border-color:var(--eno-primary,#0059bb)}
.eno-quiz-widget .eno-quiz-option:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-option[aria-pressed="true"]{border-color:var(--eno-primary,#0059bb);background:rgb(0 89 187 / 0.06)}
.eno-quiz-widget .eno-quiz-option[data-correct="true"].eno-quiz-revealed{border-color:var(--eno-success,#17803a);background:rgb(23 128 58 / 0.08)}
.eno-quiz-widget .eno-quiz-option[data-correct="false"].eno-quiz-revealed.eno-quiz-was-selected{border-color:var(--eno-error,#ba1a1a);background:var(--eno-error-soft,#ffdad6)}
.eno-quiz-widget .eno-quiz-option-icon{display:inline-block;width:1.1em;margin-right:.4em;font-weight:700}
.eno-quiz-widget .eno-quiz-submit{margin-top:1rem;min-height:44px;padding:.5rem 1.25rem;border-radius:8px;border:none;background:var(--eno-primary,#0059bb);color:#fff;font-weight:600;font-size:.9375rem;cursor:pointer;transition:opacity var(--eno-motion-base,180ms ease-out)}
.eno-quiz-widget .eno-quiz-submit:disabled{opacity:.5;cursor:not-allowed}
.eno-quiz-widget .eno-quiz-submit:focus-visible{outline:none;box-shadow:0 0 0 3px rgb(0 89 187 / 0.15)}
.eno-quiz-widget .eno-quiz-explanation{margin-top:1rem;padding:.875rem 1rem;border-radius:8px;font-size:.9375rem;line-height:1.5;display:none}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-visible{display:block}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-correct{background:rgb(23 128 58 / 0.08);color:var(--eno-success,#17803a)}
.eno-quiz-widget .eno-quiz-explanation.eno-quiz-incorrect{background:var(--eno-error-soft,#ffdad6);color:var(--eno-error,#ba1a1a)}
@media (prefers-reduced-motion: reduce){.eno-quiz-widget *{transition:none!important}}
</style><div class="eno-quiz-widget" role="group" aria-label="Question rapide">
Question rapide 2 sur 2

Quelle commande est utilisée pour ajouter un taint à un nœud ?

- kubectl add taint
- kubectl taint
- kubectl set taint
- kubectl patch node

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">La commande correcte pour ajouter un taint à un nœud est `kubectl taint nodes node1 key1=value1:NoSchedule`.</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.eno-quiz-widget:not([data-eno-quiz-bound])').forEach(function (widget) {
    widget.setAttribute('data-eno-quiz-bound', '1');
    var options = Array.prototype.slice.call(widget.querySelectorAll('.eno-quiz-option'));
    var submitBtn = widget.querySelector('.eno-quiz-submit');
    var explanation = widget.querySelector('.eno-quiz-explanation');
    var selected = null;
    options.forEach(function (opt) {
      opt.addEventListener('click', function () {
        if (widget.hasAttribute('data-eno-quiz-answered')) return;
        options.forEach(function (o) { o.setAttribute('aria-pressed', 'false'); });
        opt.setAttribute('aria-pressed', 'true');
        selected = opt;
        submitBtn.disabled = false;
      });
    });
    submitBtn.addEventListener('click', function () {
      if (!selected || widget.hasAttribute('data-eno-quiz-answered')) return;
      widget.setAttribute('data-eno-quiz-answered', '1');
      submitBtn.disabled = true;
      var correct = selected.getAttribute('data-correct') === 'true';
      options.forEach(function (o) {
        o.classList.add('eno-quiz-revealed');
        if (o === selected) o.classList.add('eno-quiz-was-selected');
        var icon = o.querySelector('.eno-quiz-option-icon');
        if (o.getAttribute('data-correct') === 'true') icon.textContent = '\u2713';
        else if (o === selected) icon.textContent = '\u2717';
      });
      explanation.classList.add('eno-quiz-visible', correct ? 'eno-quiz-correct' : 'eno-quiz-incorrect');
    });
  });
});
</script>

## 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 PreferNoSchedule pour é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-ready a 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.

<div class="my-stack-md overflow-x-auto">
<table class="min-w-[42rem] border-collapse text-left">
<thead><tr><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Étape</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Action</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Commande / Vérification</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Résultat attendu</th></tr></thead>
<tbody><tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">1</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Enregistrer la version actuelle du cluster et les taints des nœuds</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl version --short</code> et <code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints</code></td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Version listée, taints visibles</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">2</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Identifier les taints et tolérances cibles</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Documenter l&#39;état souhaité</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Liste claire des changements</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">3</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Ajouter les tolérances aux pods avant d&#39;ajouter les taints</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Modifier la spécification du Deployment ou du Pod, appliquer, <code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl rollout status</code></td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Déploiement réussi</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">4</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Ajouter le taint à un seul nœud de test</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl taint nodes &lt;node&gt; key=value:NoSchedule</code></td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Le taint apparaît dans la spécification du nœud</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">5</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier l&#39;ordonnancement des pods sur le nœud de test</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get pods -o wide</code> et <code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl describe pod</code></td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Pod ordonnancé sur le nœud prévu</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">6</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Surveiller les évictions</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant"><code class="font-mono text-[0.9em] bg-surface-container px-1 py-0.5 rounded">kubectl get events --all-namespaces --field-selector reason=Evicted</code></td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Aucune éviction inattendue</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">7</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Déployer sur les nœuds restants de manière incrémentale</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Répéter l&#39;ajout de taint pour chaque nœud, en vérifiant entre chaque</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Tous les nœuds taints, aucun problème</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">8</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Mettre à jour la documentation et les runbooks</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Enregistrer les commandes et sorties réelles</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Documentation à jour</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">9</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Planifier une validation périodique</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">par exemple, script hebdomadaire pour comparer les taints des nœuds et les tolérances des pods</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Dérive détectée tôt</td></tr></tbody>
</table>
</div>

### 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 describe et 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.