Kubernetes
8 min de lecture

Kubernetes production-ready : les bonnes pratiques résilience

PDB, anti-affinity, topology spread, probes, graceful shutdown... Les mécanismes Kubernetes indispensables pour une application qui tient en production.

Arthur Zinck
Arthur Zinck
Expert DevOps Kubernetes & Cloud

J’ai accompagné des dizaines d’équipes de développeurs sur Kubernetes. Les mêmes problèmes reviennent systématiquement. Il est temps de faire le bilan.

Le design stateless d’abord

Avant de parler configuration Kubernetes, il faut parler architecture. Si l’application stocke des sessions en mémoire, des fichiers temporaires sur disque, ou maintient un état interne entre les requêtes, aucune config Kubernetes ne la sauvera.

Kubernetes part du principe que les pods sont jetables. Un pod peut être tué à n’importe quel moment : node qui scale down, preemption Spot, rolling update, OOM. Si l’application ne supporte pas ça, c’est elle le problème.

Règle simple : tout ce qui doit persister va dans un service externe. Sessions dans Redis, fichiers dans S3, état dans une base de données. Le pod démarre, fait son travail, peut mourir sans que personne ne pleure. Ça marche dans 95% des cas. Pour le reste, il y a les StatefulSets, mais c’est un autre sujet.

Les probes : liveness, readiness, startup

Trois probes, trois rôles distincts.

La liveness probe répond à une question : est-ce que le conteneur est vivant ? Si elle échoue, Kubernetes tue le pod et en crée un nouveau. C’est le dernier recours, le bouton reset. Elle doit vérifier que le processus principal fonctionne, pas que l’application est prête à recevoir du trafic.

La readiness probe répond à une autre question : est-ce que le pod peut recevoir du trafic ? Si elle échoue, Kubernetes retire le pod du Service. Plus de requêtes envoyées. Mais le pod continue de vivre. Utile quand l’application a besoin de temps pour se reconfigurer, recharger un cache, ou se reconnecter à une dépendance.

La startup probe est souvent oubliée. Elle désactive les autres probes pendant le démarrage. Pour une application Java qui met 45 secondes à s’initialiser, c’est indispensable. Sans elle, la liveness probe tue le pod avant qu’il ait fini de démarrer. CrashLoopBackOff.

Une erreur classique : mettre la même URL pour liveness et readiness. Si l’application vérifie ses dépendances (base de données, Redis) dans le health check, et que Redis est temporairement indisponible, tous les pods se font tuer. Alors que retirer le trafic aurait suffi.

Ce que je dis aux équipes : la liveness c’est brutal, un kill. Elle doit être sûre que le process est vraiment mort avant de tirer. La readiness, c’est l’inverse : agressive, elle doit retirer le pod du trafic au moindre doute. Et la startup, il faut checker souvent et longtemps. Si le pod démarre sur un node chargé, ça peut prendre plus de temps que prévu. Mieux vaut attendre que de CrashLoop.

Le graceful shutdown

Le pod reçoit un SIGTERM. L’application a quelques secondes pour terminer proprement. Si elle ne gère pas ce signal, Kubernetes envoie un SIGKILL et les connexions en cours sont coupées net. Des requêtes perdues, des transactions incomplètes.

Côté application, il faut intercepter le SIGTERM et finir les requêtes en cours avant de s’arrêter. La plupart des frameworks modernes le font, mais il faut vérifier.

Côté Kubernetes, le terminationGracePeriodSeconds définit le délai avant le SIGKILL. 30 secondes par défaut. Pour une application qui traite des jobs longs, il faut augmenter cette valeur.

Un détail souvent ignoré : le preStop hook. Kubernetes retire le pod du Service et envoie le SIGTERM quasi simultanément. En pratique, certaines requêtes arrivent encore pendant que l’application s’arrête. Un preStop hook avec un sleep 5 laisse le temps aux load balancers de mettre à jour leurs tables de routage avant que l’application commence son shutdown.

Pod Disruption Budget

Le PDB, c’est un contrat entre vous et Kubernetes. “Tu peux faire ta maintenance, mais tu me garantis qu’il reste toujours X pods disponibles.”

Sans PDB, Kubernetes peut drainer tous les pods d’un Deployment en même temps pendant une mise à jour du cluster. Avec un PDB qui dit minAvailable: 2, Kubernetes attendra qu’un pod soit reschedulé et Ready avant d’en évacuer un autre.

Pour un Deployment avec 3 replicas, un PDB avec maxUnavailable: 1 garantit qu’au moins 2 pods tournent en permanence. Les rolling updates, les maintenances de node, les upgrades de cluster respectent cette contrainte.

Attention : le PDB ne protège pas contre les crashes applicatifs ou les OOM. Il protège contre les disruptions volontaires initiées par Kubernetes ou les opérateurs.

Pod Anti-Affinity

Trois replicas d’une application critique. Les trois sur le même node. Le node tombe. L’application est down.

L’anti-affinity résout ce problème. Elle dit au scheduler : “ne mets pas deux pods de ce Deployment sur le même node”. Ou plus finement : “préfère les répartir sur des nodes différents, mais ne bloque pas si c’est impossible”.

Le mode requiredDuringSchedulingIgnoredDuringExecution est strict. Si aucun node ne respecte la contrainte, le pod reste Pending. Le mode preferredDuringSchedulingIgnoredDuringExecution est souple. Kubernetes fait au mieux, mais schedule quand même si nécessaire.

Pour les applications critiques, je combine les deux : required pour la répartition inter-node, preferred pour la répartition inter-zone.

Topology Spread Constraints

L’anti-affinity, c’est bien. Les topology spread constraints, c’est plus puissant.

L’anti-affinity dit “pas deux pods sur le même node”. Les topology spread constraints disent “répartis les pods uniformément sur les zones/nodes/racks”. La différence : avec 6 pods et 3 zones, l’anti-affinity peut mettre 4 pods dans une zone et 1 dans chaque autre. Les topology spread constraints garantissent 2 pods par zone.

Le paramètre maxSkew définit l’écart maximum toléré entre les zones. Avec maxSkew: 1, la différence entre la zone la plus chargée et la moins chargée ne peut pas dépasser 1 pod.

Sur les clusters multi-AZ, c’est ma configuration par défaut pour les workloads critiques.

A noter que les Pods en Pending sont souvent le trigger de scale-up pour les nodes

Déploiement Multi-AZ

Avoir des pods répartis sur plusieurs zones, c’est bien. Encore faut-il que les nodes existent dans ces zones.

Sur EKS, ça veut dire des node groups configurés avec des subnets dans plusieurs AZ. Sur un cluster autoscalé avec Karpenter ou Cluster Autoscaler, il faut que les provisioners soient configurés pour créer des nodes dans toutes les zones.

Le coût : le trafic cross-AZ est facturé. 0.01 $/Go dans chaque sens sur AWS. Pour des applications qui communiquent beaucoup entre elles, ça peut représenter un coût significatif. C’est le prix de la résilience.

Un compromis que j’utilise parfois : le topology aware routing. Une annotation sur le Service (service.kubernetes.io/topology-mode: Auto) et kube-proxy préfère router le trafic vers les pods de la même zone. Moins de latence, moins de coûts réseau. Si la zone locale n’a pas assez de capacité, ça fallback sur du routing multi-AZ classique.

Les requests et limits

J’en ai parlé dans un article dédié, mais ça mérite d’être rappelé ici.

Sans requests, le scheduler ne sait pas où placer les pods. Il les empile sur les mêmes nodes jusqu’à saturation. Un node qui swap, des applications qui rament, du throttling CPU inexpliqué.

Règle simple : requests mémoire égales aux limits, pas de limits CPU. Le scheduler place les pods correctement, les applications ont la mémoire qu’elles demandent, et le CPU peut burst si le node a de la capacité.


Ces configurations ne sont pas optionnelles. C’est le minimum pour un cluster de production. Sans elles, Kubernetes fonctionne. Jusqu’au jour où ça ne fonctionne plus. Et ce jour-là, c’est toujours un vendredi soir.

Avec tout ça en place, votre cluster est prêt pour du Spot et ses 60-80% d’économies. Côté infrastructure, vous êtes couverts. Côté application, il reste du travail : idempotence, gestion des erreurs transitoires, jobs longs dans des queues. Un sujet pour un prochain article.

L’essentiel de ces pratiques s’applique aussi sur Scaleway Kapsule ou d’autres providers. Les PDB, probes, anti-affinity, topology spread : c’est du Kubernetes standard.

Besoin d’aide pour sécuriser votre cluster Kubernetes ? Contactez-moi.

kubernetes resilience pdb probes anti-affinity topology-spread multi-az production

Partager cet article

Twitter LinkedIn