## Introduction

L'affinité de nœud dans Kubernetes vous permet de contrôler sur quels nœuds vos pods seront placés en fonction des étiquettes des nœuds. Elle est plus expressive que l'ancien champ nodeSelector et prend en charge à la fois les exigences strictes et les préférences souples. Cet article explique l'architecture de l'affinité de nœud, propose des exemples pratiques et montre comment vérifier, diagnostiquer et résoudre les problèmes de planification courants.

Vous apprendrez comment le kube-scheduler évalue les règles d'affinité de nœud, comment écrire des manifestes avec des termes obligatoires et préférés, et comment combiner l'affinité avec les teintures, les tolérances et la répartition topologique pour une planification robuste. Chaque exemple inclut les commandes et les sorties attendues afin que vous puissiez reproduire les scénarios dans votre propre cluster.

## Inventaire des versions et de l'environnement

Avant d'utiliser l'affinité de nœud, vérifiez la version de votre cluster et les composants de planification impliqués. L'affinité de nœud est stable depuis Kubernetes 1.6 et est disponible dans toutes les distributions modernes. Les exemples de cet article supposent Kubernetes 1.25 ou ultérieur et un contexte kubectl fonctionnel.

### Identifier la version de votre cluster

Exécutez :

kubectl version --short 
 Sortie attendue (exemple) :

Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.3 
 Si la version de votre serveur est antérieure à 1.6, effectuez une mise à niveau avant d'utiliser l'affinité de nœud. La plupart des clusters actuels satisfont à cette exigence.

### Comprendre le rôle du kube-scheduler

Le kube-scheduler est le composant qui lit les spécifications des pods et trouve un nœud approprié. Il s'exécute en tant que pod statique dans l'espace de noms kube-system sur les nœuds du plan de contrôle. Confirmez qu'il est en cours d'exécution :

kubectl get pods -n kube-system -l component=kube-scheduler 
 La sortie attendue montre un pod de planificateur en cours d'exécution, par exemple :

NAME READY STATUS RESTARTS AGE
kube-scheduler-control-plane-1 1/1 Running 0 12d 
 Le planificateur utilise un algorithme de notation qui prend en compte les règles d'affinité de nœud pendant les phases de filtrage et de notation. Les règles strictes (requiredDuringSchedulingIgnoredDuringExecution) agissent comme des filtres, éliminant les nœuds qui ne correspondent pas. Les règles souples (preferredDuringSchedulingIgnoredDuringExecution) ajoutent du poids pendant la notation, donnant aux nœuds correspondants un rang plus élevé sans exclure les autres.

### Étiquetage de base des nœuds

L'affinité de nœud fait correspondre les exigences des pods aux étiquettes des nœuds. Listez les étiquettes actuelles de vos nœuds :

kubectl get nodes --show-labels 
 Exemple de sortie :

NAME STATUS ROLES AGE VERSION LABELS
node-1 Ready control-plane 10d v1.28.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-1,node-role.kubernetes.io/control-plane=
node-2 Ready <none> 10d v1.28.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-2,disktype=ssd,zone=us-west-2a
node-3 Ready <none> 10d v1.28.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-3,disktype=hdd,zone=us-west-2b 
 Dans cet exemple, node-2 possède l'étiquette disktype=ssd, que nous pouvons utiliser pour l'affinité.

<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

Quels sont les deux types d'affinité de nœud définis dans le passage de référence ?

- requiredDuringSchedulingIgnoredDuringExecution and preferredDuringSchedulingIgnoredDuringExecution
- dure et douce
- strict et indulgent
- obligatoire et facultatif

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">Le passage énumère explicitement deux types : requiredDuringSchedulingIgnoredDuringExecution et preferredDuringSchedulingIgnoredDuringExecution.</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

Commencez par une observation en lecture seule de l'état actuel de la planification. Ensuite, effectuez le plus petit changement démontrant l'affinité de nœud et vérifiez-le avant de l'étendre.

### Étape 1 : Observer les pods existants et leur placement sur les nœuds

Exécutez :

kubectl get pods -o wide --all-namespaces 
 Cela montre où les pods sont actuellement exécutés. Si vous avez un espace de noms spécifique, utilisez -n <namespace> .

### Étape 2 : Concevoir un manifeste minimal d'affinité de nœud

Créez un fichier nommé nginx-affinity.yaml :

apiVersion: v1
kind: Pod
metadata:
 name: nginx-affinity
spec:
 containers:
 - name: nginx
 image: nginx:1.25
 ports:
 - containerPort: 80
 affinity:
 nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchExpressions:
 - key: disktype
 operator: In
 values:
 - ssd 
 Ce pod exige un nœud avec l'étiquette disktype=ssd . Il ne sera planifié que sur node-2 dans notre cluster d'exemple.

### Étape 3 : Appliquer le manifeste

kubectl apply -f nginx-affinity.yaml 
 Sortie attendue :

pod/nginx-affinity created 

### Étape 4 : Vérifier la planification

 Vérifiez le statut du pod et le nœud :

kubectl get pod nginx-affinity -o wide 
 Exemple de sortie :

NAME READY STATUS RESTARTS AGE IP NODE
nginx-affinity 1/1 Running 0 15s 10.244.2.5 node-2 
 Le pod s'exécute sur node-2, ce qui correspond à l'étiquette. Si aucun nœud ne correspond, le pod reste à l'état Pending. Nous verrons cela dans la section sur les modes d'échec.

### Étape 5 : Inspecter les événements de planification

Utilisez kubectl describe pod nginx-affinity pour voir les événements :

Events:
 Type Reason Age From Message
 ---- ------ ---- ---- -------
 Normal Scheduled 25s default-scheduler Successfully assigned default/nginx-affinity to node-2
 Normal Pulling 24s kubelet Pulling image "nginx:1.25"
 Normal Started 23s kubelet Started container nginx
 Normal Created 23s kubelet Created container nginx 
 L'événement Scheduled confirme que le planificateur a utilisé la règle d'affinité.

## Vérification et diagnostics

Maintenant qu'une règle obligatoire de base fonctionne, étendons aux règles préférées et combinons l'affinité avec d'autres fonctionnalités de planification.

### Exemple d'affinité de nœud préférée

Créez nginx-pref-affinity.yaml :

apiVersion: v1
kind: Pod
metadata:
 name: nginx-pref
spec:
 containers:
 - name: nginx
 image: nginx:1.25
 affinity:
 nodeAffinity:
 preferredDuringSchedulingIgnoredDuringExecution:
 - weight: 80
 preference:
 matchExpressions:
 - key: zone
 operator: In
 values:
 - us-west-2a
 - weight: 20
 preference:
 matchExpressions:
 - key: disktype
 operator: In
 values:
 - ssd 
 Ce pod préfère les nœuds dans la zone us-west-2a avec un poids plus élevé (80) et préfère également les nœuds ssd avec un poids de 20. Si aucun nœud ne correspond, il sera quand même planifié sur n'importe quel nœud car il n'y a pas de règle obligatoire.

Appliquez et vérifiez :

kubectl apply -f nginx-pref-affinity.yaml
kubectl get pod nginx-pref -o wide 
 Exemple de sortie :

NAME READY STATUS RESTARTS AGE IP NODE
nginx-pref 1/1 Running 0 10s 10.244.1.7 node-2 
 Il s'exécute sur node-2, ce qui correspond aux deux préférences. Si node-2 était indisponible, il pourrait s'exécuter sur node-1 ou node-3.

### Utiliser matchFields avec le nom du nœud

Vous pouvez cibler un nœud spécifique en utilisant son nom, bien que cela soit moins flexible que les étiquettes. Exemple :

affinity:
 nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchFields:
 - key: metadata.name
 operator: In
 values:
 - node-2 
 Cette exigence stricte force le pod sur node-2. Utilisez-la avec parcimonie car elle réduit la résilience de la planification.

### Combiner l'affinité de nœud avec les demandes de ressources

Ajoutez des demandes de ressources pour influencer la notation et éviter la surallocation. Par exemple, un pod gourmand en mémoire :

apiVersion: v1
kind: Pod
metadata:
 name: mem-pod
spec:
 containers:
 - name: mem-container
 image: polinux/stress
 resources:
 requests:
 memory: "512Mi"
 cpu: "250m"
 affinity:
 nodeAffinity:
 requiredDuringSchedulingIgnoredDuringExecution:
 nodeSelectorTerms:
 - matchExpressions:
 - key: disktype
 operator: Exists 
 Ce pod exige un nœud avec l'étiquette disktype (n'importe quelle valeur) et demande des ressources. Le planificateur filtre les nœuds par étiquette, puis par capacité disponible.

### Commandes de diagnostic pour le dépannage

Lorsqu'un pod avec affinité de nœud est en attente, utilisez ces commandes :

# Vérifier les événements du pod
kubectl describe pod <pod-name>

# Vérifier les étiquettes des nœuds pour voir s'il y a des correspondances
kubectl get nodes --show-labels

# Obtenir les journaux du planificateur (si vous y avez accès)
kubectl logs -n kube-system kube-scheduler-control-plane-1 | grep -i affinity 
 Les journaux du planificateur peuvent montrer pourquoi des nœuds ont été rejetés. Recherchez des messages comme "node(s) didn't match node selector" ou "0/3 nodes are available: 3 node(s) didn't match node affinity/selector." C'est l'événement standard pour les échecs.

<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

Selon le passage, que signifie « IgnoredDuringExecution » dans le contexte de l'affinité de nœud ?

- Si les labels de nœud changent après la planification, le pod continue de s'exécuter
- La règle est ignorée pendant la planification mais appliquée après
- La règle n'est appliquée que pendant l'exécution
- Si les labels de nœud changent, le pod est replanifié

<button type="button" class="eno-quiz-submit" disabled>Valider</button>
<div class="eno-quiz-explanation">Le passage indique : « IgnoredDuringExecution signifie que si les labels de nœud changent après que Kubernetes planifie le Pod, le Pod continue de s&#39;exécuter. »</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 d'échec et récupération

L'affinité de nœud peut laisser des pods en attente si les exigences sont trop strictes ou si les étiquettes sont mal configurées. Voici des scénarios d'échec courants et comment récupérer.

### Scénario 1 : Aucun nœud ne correspond à l'affinité obligatoire

Supposons que vous appliquez un pod exigeant disktype=nvme , mais qu'aucun nœud n'a cette étiquette. Le pod reste Pending.

Vérifiez :

kubectl get pod nvme-pod
kubectl describe pod nvme-pod 
 La sortie de describe inclut :

Events:
 Type Reason Age From Message
 ---- ------ ---- ---- -------
 Warning FailedScheduling 12s default-scheduler 0/3 nodes are available: 3 node(s) didn't match node affinity/selector. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling. 
 Options de récupération :

- Vérifiez si l'étiquette est manquante ou mal orthographiée. Ajoutez l'étiquette à un nœud :

kubectl label node node-3 disktype=nvme 

- Modifiez la spécification du pod pour utiliser une préférence plus souple ou supprimer l'exigence.

- Si le pod fait partie d'un déploiement, modifiez le déploiement pour corriger l'affinité, puis redémarrez le déploiement :

 kubectl edit deployment <deployment-name>
# changer l'affinité, enregistrer et quitter
kubectl rollout status deployment/<deployment-name> 

### Scénario 2 : L'affinité entre en conflit avec les teintures

 Un nœud peut avoir l'étiquette requise mais aussi une teinture que le pod ne tolère pas. Exemple : node-2 a la teinture dedicated=special:NoSchedule . Le pod avec affinité pour node-2 mais sans tolérance ne sera pas planifié.

Diagnostiquez :

kubectl get node node-2 -o json | jq '.spec.taints' 
 Exemple de sortie :

[
 {
 "effect": "NoSchedule",
 "key": "dedicated",
 "value": "special"
 }
] 
 Récupération :

- Ajoutez une tolérance à la spécification du pod :

tolerations:
- key: dedicated
 operator: Equal
 value: special
 effect: NoSchedule 

- Ou supprimez la teinture si elle n'est pas nécessaire :

 kubectl taint nodes node-2 dedicated=special:NoSchedule- 

### Scénario 3 : Pod bloqué en terminaison ou non planifiable après la perte d'un nœud

 Si un nœud correspondant à l'affinité tombe en panne, les pods avec affinité obligatoire vers ce nœud ne seront pas replanifiés ailleurs car aucun autre nœud ne satisfait la règle. Utilisez kubectl get pods -o wide pour voir l'état du nœud. Si le nœud est NotReady, les pods peuvent être bloqués en Terminating ou Pending.

Récupération :

- Évacuez manuellement le pod :

kubectl delete pod <pod-name> --force --grace-period=0 

- Ensuite, ajoutez l'étiquette manquante à un autre nœud ou changez l'affinité en règle préférée.

## Liste de contrôle opérationnelle

 Utilisez cette liste de contrôle avant et après avoir effectué des modifications d'affinité de nœud en production.

### Avant d'appliquer les modifications

- [ ] Exécutez kubectl get nodes --show-labels et enregistrez les étiquettes actuelles des nœuds candidats.

- [ ] Exécutez kubectl get pods -o wide dans l'espace de noms cible pour voir le placement existant.

- [ ] Vérifiez que le planificateur est sain : kubectl get pods -n kube-system -l component=kube-scheduler

- [ ] Examinez les teintures sur les nœuds qui doivent correspondre : kubectl describe nodes | grep Taints

- [ ] Décidez si vous avez besoin d'une affinité obligatoire ou préférée. Préférez les règles préférées pour la haute disponibilité, sauf si vous avez une exigence matérielle stricte.

- [ ] Écrivez le manifeste YAML et validez-le avec kubectl apply --dry-run=client -f manifest.yaml

### Après avoir appliqué les modifications

- [ ] Vérifiez que les pods sont planifiés : kubectl get pods -o wide

- [ ] Vérifiez les événements pour les avertissements FailedScheduling : kubectl describe pod - [ ] Si vous utilisez un déploiement, confirmez le succès du déploiement : kubectl rollout status deployment/ 

- [ ] Testez le comportement en cordonnant un nœud correspondant et en voyant si les pods se replanifient selon les règles d'affinité (si préférée) ou restent en attente (si obligatoire).

- [ ] Documentez le changement dans votre runbook avec les étiquettes exactes et les termes d'affinité utilisés.

### Référence rapide des opérateurs d'affinité courants

 Opérateur Signification Exemple 
 In La valeur de l'étiquette est dans la liste disktype In [ssd, nvme] 
 NotIn La valeur de l'étiquette n'est pas dans la liste zone NotIn [us-west-2b] 
 Exists La clé d'étiquette existe quelle que soit la valeur disktype Exists 
 DoesNotExist La clé d'étiquette n'existe pas gpu DoesNotExist 
 Gt La valeur de l'étiquette est supérieure à un entier (non pris en charge pour les valeurs d'étiquette) cpu-count Gt 4 (non valide pour l'affinité) 
 Lt La valeur de l'étiquette est inférieure à un entier Similaire à ci-dessus 

 Remarque : Les opérateurs Gt et Lt ne sont pas valides pour les matchExpressions basés sur les étiquettes dans l'affinité de nœud ; ils ne sont pas pris en charge du tout dans l'affinité de nœud. Tenez-vous-en à In, NotIn, Exists, DoesNotExist.

## Conclusion

L'affinité de nœud vous donne un contrôle précis sur le placement des pods tout en maintenant la clarté de vos manifestes. En utilisant des étiquettes, des expressions de correspondance et des poids, vous pouvez construire des politiques de planification qui reflètent la topologie de votre infrastructure et les exigences de vos applications.

Commencez toujours par un petit test, vérifiez les événements de planification et préférez les règles souples à moins qu'une contrainte stricte ne soit nécessaire. Combinez l'affinité de nœud avec les tolérances, les demandes de ressources et les contraintes de répartition topologique pour créer des déploiements résilients et efficaces.

Pour approfondir votre compréhension, expérimentez avec différentes expressions de correspondance, pratiquez avec les teintures et les tolérances, et surveillez le comportement du planificateur en utilisant le point de terminaison des métriques. L'affinité de nœud est un outil fondamental du planificateur Kubernetes, et sa maîtrise vous rendra plus efficace dans la gestion des clusters de production.