E-NO
Kubernetes 8 min de lecture

Durcissement de la sécurité de l'affinité et de l'anti-affinité des pods Kubernetes : guide pratique de mise en œuvre

calendar_today Publié : 2026-08-25
update Dernière mise à jour : 2026-08-25
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Durcissement de la sécurité de l'affinité et de l'anti-affinité des pods Kubernetes : guide pratique de mise en œuvre ».

Introduction

L'affinité et l'anti-affinité des pods sont des fonctionnalités de planification de Kubernetes qui vous permettent de contrôler sur quels nœuds vos pods atterrissent, en fonction des étiquettes des autres pods déjà en cours d'exécution sur ces nœuds. Elles sont puissantes pour la performance, la haute disponibilité et la conformité, mais elles introduisent également des risques de sécurité si elles sont mal configurées. Par exemple, une règle d'anti-affinité trop large peut empêcher des pods critiques d'être planifiés, provoquant un déni de service. Une règle d'affinité trop permissive peut involontairement colocaliser des charges de travail sensibles avec des pods moins fiables, augmentant le rayon d'impact d'une compromission.

Ce guide s'adresse aux ingénieurs de plateforme, aux consultants DevOps et aux équipes techniques de startups qui doivent durcir les configurations d'affinité et d'anti-affinité des pods Kubernetes sans casser leurs clusters. Nous nous concentrons sur des étapes pratiques et vérifiables : observer avant de changer, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier les résultats et documenter les chemins de récupération.

À la fin de cet article, vous serez capable de :

  • Inventorier votre version et votre environnement Kubernetes actuels pour connaître les fonctionnalités d'affinité disponibles.
  • Appliquer des changements de configuration en toute sécurité à l'aide de manifestes avec des règles explicites et minimales.
  • Vérifier que vos paramètres d'affinité et d'anti-affinité fonctionnent comme prévu à l'aide des commandes kubectl.
  • Diagnostiquer et récupérer des modes de défaillance courants, tels que les pods non planifiables.
  • Suivre une liste de contrôle opérationnelle pour maintenir la sécurité au fil du temps.

Tout au long, nous utilisons des commandes concrètes, des extraits de manifestes et des sorties attendues afin que vous puissiez suivre sur votre propre cluster.

Inventaire de la version et de l'environnement

Avant de durcir l'affinité et l'anti-affinité des pods, vous devez connaître votre version de Kubernetes et les spécificités de votre environnement. L'affinité et l'anti-affinité sont stables depuis Kubernetes 1.14, mais les versions antérieures peuvent manquer de certains champs (par exemple, namespaceSelector pour l'affinité inter-namespaces). Vérifiez également si vous utilisez un service Kubernetes géré (EKS, GKE, AKS) ou un cluster auto-géré, car cela affecte la manière dont vous appliquez les changements et le contrôle d'accès.

Prérequis clés pour ce guide :

  • Cluster Kubernetes version 1.19 ou ultérieure (pour utiliser tous les champs d'affinité en toute sécurité).
  • kubectl installé et configuré avec les autorisations appropriées (au moins get, describe, logs et apply sur les pods, déploiements et namespaces).
  • Un namespace de test (par exemple, affinity-test) où vous pouvez expérimenter en toute sécurité sans affecter la production.

Étape 1 : Vérifier la version du cluster

Exécutez :

kubectl version --short

Sortie attendue similaire à :

Client Version: v1.27.3
Server Version: v1.27.3

Si la version du serveur est inférieure à 1.14, vous devez effectuer une mise à niveau avant d'utiliser les fonctionnalités d'affinité avancées.

Étape 2 : Observer l'état actuel de la planification

Avant d'effectuer des changements, capturez l'état actuel. Par exemple, listez tous les pods avec leurs nœuds et leur statut :

kubectl get pods -A -o wide

Cela affiche NODE, STATUS et AGE. Notez tous les pods qui utilisent déjà des règles d'affinité :

kubectl get pods -A -o json | jq '.items[] | select(.spec.affinity != null) | .metadata.name'

Cette commande en lecture seule révèle l'utilisation existante de l'affinité sans rien modifier.

Étape 3 : Protéger les informations d'identification et le matériel privé

Lorsque vous travaillez avec des manifestes, évitez d'incorporer des secrets. Utilisez des espaces réservés et des variables d'environnement. Nous discuterons de la gestion des secrets plus tard.

Étape 4 : Changement le plus petit justifié

Pour votre première tâche de durcissement, choisissez un seul déploiement et une seule règle d'affinité. Ne réécrivez pas toutes les politiques de planification en une seule fois.

Vérification pratique :

kubectl get pods -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>

Dans la sortie de describe, cherchez la section Events. Si un pod n'est pas planifiable en raison de l'affinité, vous verrez un message comme :

0/3 nodes are available: 3 node(s) didn't match pod affinity/anti-affinity rules.

C'est un signal clair que votre règle est trop restrictive.

Exemple d'inventaire d'environnement :

Créons un namespace de test et un déploiement simple à utiliser tout au long de ce guide.

apiVersion: v1
kind: Namespace
metadata:
  name: affinity-test

Appliquez-le :

kubectl apply -f namespace.yaml

Créez un déploiement nginx simple avec trois réplicas :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-baseline
  namespace: affinity-test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-baseline
  template:
    metadata:
      labels:
        app: nginx-baseline
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Appliquez et vérifiez :

kubectl apply -f nginx-baseline.yaml
kubectl rollout status deployment/nginx-baseline -n affinity-test

Attendez :

deployment "nginx-baseline" successfully rolled out

Vous avez maintenant une base de référence pour la comparaison.

Question rapide 1 sur 2

Quel est l'objectif de l'affinité et de l'anti-affinité inter-pods dans Kubernetes ?

L'affinité et l'anti-affinité inter-pods permettent de contraindre les nœuds sur lesquels vos Pods peuvent être planifiés en fonction des labels des Pods déjà exécutés sur ce nœud, plutôt que des labels des nœuds.

Chemin de configuration sûr

Maintenant, nous durcissons le déploiement en ajoutant des règles d'affinité et d'anti-affinité, mais de manière contrôlée. Le chemin sûr implique :

  1. Définir des objectifs clairs (par exemple, répartir les réplicas sur les nœuds, garder les pods sensibles à l'écart des pods généraux).
  2. Utiliser des étiquettes pour cibler les pods de manière appropriée.
  3. Appliquer un manifeste à la fois et vérifier chaque changement.
  4. Garder le rayon d'impact petit en commençant par un seul namespace et un nombre limité de réplicas.

Étape 1 : Comprendre les types d'affinité

  • Affinité de nœud : concerne les nœuds sur lesquels un pod peut être planifié en fonction des étiquettes de nœud. (Pas l'objet principal ici, mais souvent utilisée ensemble.)
  • Affinité de pod : attire les pods les uns vers les autres en fonction des étiquettes de pod.
  • Anti-affinité de pod : repousse les pods les uns des autres.

Pour le durcissement de la sécurité, l'anti-affinité est souvent plus critique car elle empêche la colocalisation de charges de travail sensibles. Par exemple, vous pourriez ne pas vouloir que vos pods de traitement des paiements soient sur le même nœud que vos pods Web publics.

Étape 2 : Ajouter de l'anti-affinité au déploiement de base

Nous allons modifier le déploiement nginx pour répartir ses pods sur les nœuds en utilisant podAntiAffinity avec preferredDuringSchedulingIgnoredDuringExecution. C'est une règle douce ; elle essaiera de placer les pods sur différents nœuds, mais planifiera quand même si c'est impossible.

Créez un nouveau manifeste nginx-anti-affinity.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-spread
  namespace: affinity-test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-spread
  template:
    metadata:
      labels:
        app: nginx-spread
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - nginx-spread
              topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Explication :

  • preferredDuringSchedulingIgnoredDuringExecution est doux ; le poids (100) signifie qu'il est fortement préféré.
  • Le podAffinityTerm sélectionne les pods avec l'étiquette app=nginx-spread.
  • topologyKey: kubernetes.io/hostname signifie que la règle est par nœud (nom d'hôte).

Appliquez :

kubectl apply -f nginx-anti-affinity.yaml
kubectl rollout status deployment/nginx-spread -n affinity-test

Étape 3 : Vérifier le placement

Vérifiez sur quels nœuds les pods se trouvent :

kubectl get pods -n affinity-test -l app=nginx-spread -o wide

Regardez la colonne NODE. Sur un cluster multi-nœuds, vous devriez voir chaque pod sur un nœud différent. Si votre cluster n'a qu'un seul nœud, ils seront tous sur le même nœud, mais la règle douce le permet.

Étape 4 : Durcir avec une anti-affinité requise

Pour une sécurité plus stricte, utilisez requiredDuringSchedulingIgnoredDuringExecution. C'est une règle dure ; si elle ne peut pas être satisfaite, le pod reste non planifié. C'est utile pour les frontières de sécurité critiques, mais peut causer des problèmes de disponibilité s'il n'y a pas assez de nœuds.

Exemple : créez un déploiement avec une anti-affinité requise pour deux réplicas :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-required-spread
  namespace: affinity-test
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-required-spread
  template:
    metadata:
      labels:
        app: nginx-required-spread
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx-required-spread
            topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:1.25

Appliquez puis essayez de passer à 4 réplicas sur un cluster à 2 nœuds :

kubectl apply -f nginx-required-spread.yaml
kubectl scale deployment nginx-required-spread --replicas=4 -n affinity-test

Vérifiez le statut des pods :

kubectl get pods -n affinity-test -l app=nginx-required-spread -o wide

Vous verrez probablement deux pods en cours d'exécution (Running) et deux en attente (Pending). Décrivez un pod en attente :

kubectl describe pod <pending-pod-name> -n affinity-test

Dans les événements, vous verrez :

0/2 nodes are available: 2 node(s) didn't match pod anti-affinity rules.

Cela démontre le compromis : l'anti-affinité stricte impose la séparation mais limite la densité.

Considérations de sécurité pour le chemin sûr :

  • Utilisez toujours des étiquettes spécifiques et peu susceptibles d'entrer en collision avec d'autres charges de travail. Évitez d'utiliser des étiquettes larges comme tier: frontend sans une étiquette d'application unique.
  • Limitez qui peut modifier les règles d'affinité à l'aide de RBAC. Seuls les utilisateurs avec les autorisations patch ou update sur les déploiements peuvent changer la planification, donc limitez cet accès.
  • Ne mettez jamais d'informations sensibles dans les étiquettes ; les étiquettes ne sont pas chiffrées et peuvent être lues par toute personne ayant un accès de liste de pods.
  • Utilisez l'isolation par namespace : combinez l'affinité avec namespaceSelector pour empêcher les interférences inter-namespaces.

Exemple d'anti-affinité étendue au namespace :

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - payment-processor
      namespaceSelector:
        matchLabels:
          environment: production
      topologyKey: kubernetes.io/hostname

Cela garantit que les pods payment-processor ne colocalisent pas avec un pod dans un namespace étiqueté environment=production.

Vérification et diagnostic

Après avoir appliqué les changements d'affinité, vous devez vérifier qu'ils fonctionnent comme prévu et diagnostiquer tout problème. Cette section couvre les commandes clés et l'interprétation.

1. Vérifier les événements de planification

Décrivez toujours les pods pour voir les événements du planificateur :

kubectl describe pod <pod-name> -n <namespace>

Cherchez la section Events. Une planification réussie affiche :

Successfully assigned affinity-test/nginx-spread-xyz to node-1

Un échec dû à l'affinité affiche :

0/3 nodes are available: 3 node(s) didn't match pod affinity/anti-affinity rules.

2. Inspecter le placement des pods par rapport aux règles

Utilisez kubectl get pods -o wide pour vérifier la répartition sur les nœuds. Pour une vérification plus programmatique, utilisez jq pour voir quels pods sont sur quels nœuds :

kubectl get pods -n affinity-test -l app=nginx-spread -o json | jq -r '.items[] | .metadata.name + " -> " + .spec.nodeName'

Sortie attendue :

nginx-spread-abc -> node-1
nginx-spread-def -> node-2
nginx-spread-ghi -> node-3

3. Tester la communication pod-à-pod (si pertinent)

Si votre affinité est pour des raisons de performance (par exemple, garder les pods de cache près des pods d'application), vous pouvez tester la latence ou le débit du réseau. Utilisez kubectl exec pour exécuter des commandes dans un pod :

kubectl exec -it <app-pod> -n affinity-test -- curl http://<cache-service>

Vérifiez que la connexion est rapide ou autorisée par les politiques réseau.

4. Vérifier les journaux pour les erreurs de configuration

Si un pod est en boucle de crash en raison de problèmes liés à l'affinité (rare, mais possible si un conteneur d'initialisation dépend du placement du pod), vérifiez les journaux :

kubectl logs <pod-name> -n <namespace> --previous

5. Valider le YAML avant de l'appliquer

Utilisez kubectl apply --dry-run=client ou --dry-run=server pour valider les manifestes :

kubectl apply -f nginx-anti-affinity.yaml --dry-run=client

Cela détecte les erreurs de syntaxe sans changer le cluster.

Scénario de diagnostic : pod bloqué en état Pending

Supposons que vous ayez appliqué une règle d'anti-affinité requise qui ne peut pas être satisfaite. Le pod reste en attente. Étapes de diagnostic :

  1. kubectl get pods -n <namespace> pour voir le statut.
  2. kubectl describe pod <pod-name> pour voir les événements.
  3. Vérifiez le nombre de nœuds : kubectl get nodes.
  4. Vérifiez les étiquettes des pods existants : kubectl get pods -n <namespace> --show-labels.
  5. Déterminez si votre topologyKey est trop fine. Par exemple, utiliser topologyKey: kubernetes.io/hostname sur un cluster à nœud unique ne permettra jamais plus d'un pod avec la même étiquette.

Récupération : soit augmenter le nombre de nœuds, passer à une anti-affinité préférée, ou assouplir le sélecteur d'étiquettes.

Question rapide 2 sur 2

Quelle est la différence entre `requiredDuringSchedulingIgnoredDuringExecution` et `preferredDuringSchedulingIgnoredDuringExecution` dans l'affinité de nœuds ?

`requiredDuringSchedulingIgnoredDuringExecution` signifie que le planificateur ne peut pas planifier le Pod à moins que la règle ne soit respectée, tandis que `preferredDuringSchedulingIgnoredDuringExecution` signifie que le planificateur essaie de trouver un nœud correspondant mais s'il n'est pas disponible, le Pod est quand même planifié.

Modes de défaillance et récupération

Même avec une planification minutieuse, l'affinité et l'anti-affinité peuvent causer des défaillances. Cette section couvre les modes de défaillance courants et comment récupérer avec élégance.

Mode de défaillance 1 : Anti-affinité trop stricte provoque des pods non planifiables

Symptôme : Les pods restent en attente avec un message d'événement didn't match pod anti-affinity rules.

Récupération :

  • Réduisez temporairement le déploiement à un nombre qui correspond à la règle :
kubectl scale deployment <name> --replicas=<lower-number> -n <namespace>
  • Ou changez l'anti-affinité de requise à préférée en modifiant le déploiement :
kubectl edit deployment <name> -n <namespace>

Remplacez requiredDuringSchedulingIgnoredDuringExecution par preferredDuringSchedulingIgnoredDuringExecution et ajoutez un poids. Enregistrez et quittez ; le déploiement lance une nouvelle révision.

  • En dernier recours, supprimez les pods en attente :
kubectl delete pod <pending-pod-name> -n <namespace>

Le contrôleur de déploiement les recrée, mais si la règle est toujours insatisfaisable, ils se remettront en attente.

Mode de défaillance 2 : La règle d'affinité correspond accidentellement à des pods non intentionnels

Symptôme : Les pods sont planifiés sur des nœuds avec des pods qu'ils devraient éviter, ou ils se regroupent avec des pods inattendus.

Cause : Sélecteurs d'étiquettes larges, par exemple, utiliser app: web quand plusieurs applications Web s'exécutent dans le namespace.

Récupération :

  • Inspectez les étiquettes des pods en cours d'exécution :
kubectl get pods -n <namespace> --show-labels
  • Mettez à jour le sélecteur d'étiquettes du déploiement pour qu'il soit plus spécifique, par exemple, app: my-web et tier: frontend.
  • Appliquez le manifeste mis à jour et surveillez le déploiement :
kubectl apply -f updated-deployment.yaml
kubectl rollout status deployment/<name> -n <namespace>

Mode de défaillance 3 : Interférence inter-namespaces

Symptôme : Les pods dans le namespace A affectent la planification des pods dans le namespace B en raison de namespaceSelector ou d'étiquettes larges.

Récupération :

  • Utilisez namespaceSelector pour restreindre l'affinité à des namespaces spécifiques uniquement si nécessaire. Sinon, supprimez les sélecteurs inter-namespaces.
  • Assurez-vous que chaque namespace a des étiquettes distinctes.
  • Envisagez d'utiliser des politiques réseau pour isoler les namespaces, mais c'est distinct de la planification.

Mode de défaillance 4 : Dégradation des performances due à une séparation excessive

Symptôme : Les applications subissent une latence élevée car les pods dépendants sont sur des nœuds différents, imposés par l'anti-affinité.

Récupération :

  • Évaluez si l'anti-affinité est vraiment nécessaire. Pour les ensembles avec état où la localité des données compte, vous pourriez utiliser l'affinité de nœud à la place ou un mélange.
  • Utilisez preferredDuringSchedulingIgnoredDuringExecution avec un poids plus faible pour permettre la colocalisation si nécessaire.
  • Surveillez les métriques (par exemple, la latence des requêtes) avant et après les changements.

Récupération après sinistre : annuler une mauvaise configuration

Si un déploiement cause des problèmes généralisés, vous pouvez revenir à une révision précédente :

kubectl rollout undo deployment/<name> -n <namespace>

Vérifiez le statut du déploiement :

kubectl rollout status deployment/<name> -n <namespace>

Documenter la récupération

Ayez toujours un runbook pour les déploiements critiques. Incluez :

  • Comment vérifier rapidement le statut des pods.
  • Commandes sûres pour mettre à l'échelle ou modifier sans temps d'arrêt.
  • Procédure de retour en arrière.
  • Contact pour l'escalade.

Liste de contrôle opérationnelle

Utilisez cette liste de contrôle pour maintenir des configurations d'affinité et d'anti-affinité sécurisées au fil du temps.

Opérations quotidiennes

  • [ ] Vérifier qu'aucun pod n'est bloqué en attente en raison de l'affinité : kubectl get pods -A | grep Pending.
  • [ ] Vérifier le nombre de nœuds du cluster : kubectl get nodes (si des nœuds sont supprimés, l'anti-affinité requise peut échouer).
  • [ ] Examiner les événements pour les messages liés à l'affinité : kubectl get events -A | grep -i affinity.

Audits hebdomadaires

  • [ ] Lister tous les déploiements avec des règles d'affinité : kubectl get deployments -A -o json | jq '.items[] | select(.spec.template.spec.affinity != null) | .metadata.name + " in " + .metadata.namespace'.
  • [ ] Examiner les sélecteurs d'étiquettes pour la spécificité : assurez-vous qu'ils incluent des identifiants d'application uniques.
  • [ ] Vérifier les autorisations RBAC pour qui peut modifier les déploiements : kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 -A5 'deployments'.

Gestion des changements

  • [ ] Toujours tester les changements d'affinité dans un namespace non productif d'abord.
  • [ ] Utiliser kubectl apply --dry-run=server pour valider.
  • [ ] Échelonner les déploiements : appliquer les changements à un réplica ou à un canari avant le déploiement complet.
  • [ ] Avoir un plan de retour en arrière : noter la révision précédente avant d'appliquer (kubectl rollout history deployment/<name>).

Rappels de durcissement de la sécurité

  • [ ] Ne jamais utiliser de données sensibles dans les étiquettes.
  • [ ] Éviter une anti-affinité trop large qui peut causer un déni de service auto-infligé.
  • [ ] Combiner l'anti-affinité avec des politiques réseau pour une défense en profondeur.
  • [ ] Examiner régulièrement les étiquettes de nœuds et les clés de topologie utilisées.

Exemple : vérifier les règles d'affinité dans le cluster

Exécutez cette commande pour obtenir un résumé des types d'affinité utilisés :

kubectl get pods -A -o json | jq -r '.items[] | select(.spec.affinity != null) | .metadata.namespace + "/" + .metadata.name + " has affinity"' | sort

Cela vous aide à repérer une utilisation inattendue.

Conclusion

L'affinité et l'anti-affinité des pods Kubernetes sont des outils puissants pour contrôler le placement des pods, mais ils doivent être configurés avec la sécurité à l'esprit. Une règle d'anti-affinité mal configurée peut conduire à des pods non planifiables et à des pannes de service ; une règle d'affinité permissive peut compromettre l'isolation et augmenter les risques.

Dans ce guide, nous avons couvert :

  • Vérifier votre version de Kubernetes et l'inventaire de l'environnement.
  • Appliquer des règles d'affinité et d'anti-affinité en toute sécurité, en commençant par des règles douces et en progressant vers des règles dures.
  • Vérifier les décisions de planification avec les commandes kubectl et comprendre les messages d'événements.
  • Diagnostiquer et récupérer des défaillances courantes telles que les pods en attente et la colocalisation non intentionnelle.
  • Suivre une liste de contrôle opérationnelle pour maintenir la sécurité et la disponibilité.

Prochaines étapes :

  1. Choisissez un déploiement à faible risque dans un namespace de test.
  2. Ajoutez une règle d'anti-affinité preferredDuringSchedulingIgnoredDuringExecution pour répartir les réplicas.
  3. Surveillez le placement des pods et notez tout changement.
  4. Durcissez progressivement vers des règles requises le cas échéant, en ayant toujours un plan de retour en arrière.

N'oubliez pas que le durcissement de la sécurité est itératif. Observez, changez une chose, vérifiez et documentez. Avec ces pratiques, vous pouvez tirer parti de l'affinité et de l'anti-affinité des pods pour améliorer à la fois la résilience et la sécurité sans sacrifier la stabilité opérationnelle.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO