
Vos Pods Kubernetes se font tuer avec un mystérieux message OOMKilled ? Ou ils semblent tourner au ralenti malgré un serveur bien dimensionné ? Le problème vient probablement d'une mauvaise configuration des requests et limits, les paramètres qui définissent combien de CPU et de mémoire chaque Pod peut utiliser.
Ce guide vous explique comment configurer ces paramètres pour éviter les ralentissements, les crashs et la surconsommation de ressources.
Prérequis : concepts Kubernetes de base et un cluster fonctionnel.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre la différence entre requests (ressources garanties) et limits (plafonds)
- Identifier les symptômes d'une mauvaise configuration (OOMKilled, throttling)
- Choisir la bonne classe de QoS selon le type d'application
- Configurer les ressources pour des workloads critiques, élastiques et non critiques
- Diagnostiquer les problèmes avec kubectl et Prometheus
Comprendre les requests et limits
Section intitulée « Comprendre les requests et limits »Les requests et limits sont les deux paramètres qui contrôlent la consommation de ressources d'un conteneur.
Requests : le minimum garanti
Section intitulée « Requests : le minimum garanti »Les requests définissent la quantité minimale de ressources (CPU/mémoire) dont un conteneur a besoin pour fonctionner. Kubernetes réserve ces ressources sur le nœud où le Pod est déployé.
Exemple : si un Pod demande 500m CPU (soit 50% d'un CPU), Kubernetes s'assure qu'un nœud ayant au moins cette capacité disponible l'accueille.
Limits : la barrière à ne pas franchir
Section intitulée « Limits : la barrière à ne pas franchir »Les limits définissent la quantité maximale de ressources qu'un conteneur peut consommer. Si un Pod dépasse cette limite, Kubernetes applique des restrictions :
- CPU : throttling (ralentissement forcé)
- Mémoire : OOMKilled, le conteneur est tué et redémarré selon la
restartPolicy
Exemple : si un Pod a une limit de 1 CPU, il ne pourra jamais dépasser cette valeur, même en cas de forte demande.
Vérifier les ressources d'un Pod
Section intitulée « Vérifier les ressources d'un Pod »Deux choses différentes se vérifient, et les confondre fait tourner en rond : ce que le Pod déclare, qui se lit dans son manifeste, et ce qu'il consomme réellement, qui demande le serveur de métriques. Le premier explique un placement, le second explique une lenteur.
kubectl describe pod mon-pod | grep -A 10 "Limits:"Sortie attendue :
Limits: cpu: 500m memory: 256Mi Requests: cpu: 250m memory: 128MiUne surprise attend ceux qui n'ont déclaré que des limits : Kubernetes recopie
la limit dans la request au moment d'enregistrer le Pod. Un manifeste qui ne
porte que limits: {cpu: 300m, memory: 128Mi} se relit ainsi :
{"limits":{"cpu":"300m","memory":"128Mi"},"requests":{"cpu":"300m","memory":"128Mi"}}Le scheduler réserve donc bien 300m sur le nœud, et le Pod se retrouve en classe
Guaranteed sans que personne l'ait demandé. Relisez toujours le Pod après
création plutôt que votre manifeste :
kubectl get pod mon-pod -o jsonpath='{.spec.containers[0].resources}'Visualisation requests vs limits
Section intitulée « Visualisation requests vs limits »
Le request (vert) est l'espace garanti par le scheduler. La zone burst (jaune) est disponible si le nœud a de la capacité. La limit (rouge) est le plafond absolu, au-delà, c'est le throttling CPU ou l'OOMKilled mémoire.
Les problèmes d'une mauvaise configuration
Section intitulée « Les problèmes d'une mauvaise configuration »Si vous définissez mal requests et limits, vous risquez trois types de problèmes.
Throttling CPU : quand Kubernetes vous freine
Section intitulée « Throttling CPU : quand Kubernetes vous freine »Le throttling CPU se produit lorsque votre conteneur atteint sa limit CPU. Kubernetes utilise le planificateur CFS (Completely Fair Scheduler) de Linux pour le ralentir.
Symptômes :
- L'application devient lente et peu réactive
- Des timeouts apparaissent sur les requêtes
- Une baisse de performance inattendue en période de charge
Comment détecter le throttling :
kubectl top podDeux précisions avant de la taper. D'abord, cette commande ne marche pas sur
un cluster neuf : elle interroge l'API de métriques, fournie par
metrics-server, qui n'est installé ni sur kind ni sur la plupart des
distributions minimales.
error: Metrics API not availableEnsuite, kubectl top rend des valeurs absolues, en millicores et en
octets, jamais un pourcentage. Comparez vous-même la valeur affichée à la
limits.cpu du conteneur : un Pod qui plafonne à 500m avec une limite à
500m est en throttling.
La mesure qui ne se discute pas vient de Prometheus, car elle compte le temps réellement volé au conteneur plutôt que de l'inférer :
rate(container_cpu_cfs_throttled_seconds_total[5m])Une valeur non nulle signifie que le noyau a effectivement suspendu le conteneur pendant ses quotas.
Solutions :
- Évitez de définir une limit CPU si ce n'est pas nécessaire
- Augmentez la limit CPU si votre application a besoin de plus de puissance
- Utilisez le Horizontal Pod Autoscaler (HPA) pour ajouter des Pods au lieu de restreindre un seul
OOMKilled : quand votre Pod explose
Section intitulée « OOMKilled : quand votre Pod explose »Contrairement au CPU, la mémoire ne se ralentit pas : on ne peut pas rendre un octet déjà alloué. Le CPU se bride, la mémoire se reprend, et la seule façon de la reprendre est de tuer le processus. C'est le noyau qui s'en charge quand le cgroup atteint sa limite, avec le message OOMKilled.
Deux précisions que les schémas simplifiés escamotent. C'est le conteneur qui est tué, pas le Pod : ce que vous observez ensuite dépend de la restartPolicy et du contrôleur. Et le déclenchement est réactif, lié à la pression mémoire du cgroup : une charge peut brièvement frôler sa limite avant que le noyau n'intervienne.
Symptômes :
- Redémarrages en boucle (CrashLoopBackOff)
- Pertes de données si l'application ne gère pas bien les interruptions
- Instabilité du service si plusieurs Pods critiques sont affectés
Comment détecter un OOMKilled :
Le plus simple d'abord, la colonne STATUS le dit directement :
kubectl get pod mon-podNAME READY STATUS RESTARTS AGEoom 0/1 OOMKilled 0 3sAttention au champ que vous interrogez si vous scriptez. Beaucoup d'exemples
lisent lastState, qui ne contient la raison qu'après un redémarrage. Sur
un Pod en restartPolicy: Never, il est vide et la raison vit dans state :
# Le conteneur tourne encore après avoir été tué et relancékubectl get pod mon-pod \ -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'
# Le conteneur est mort et n'a pas redémarrékubectl get pod mon-pod \ -o jsonpath='{.status.containerStatuses[0].state.terminated.reason}'Interrogez les deux, ou lisez simplement kubectl describe pod, qui affiche la
Reason quel que soit le cas.
Le code de sortie lève la dernière ambiguïté, et c'est lui qu'on retrouve dans les journaux d'une chaîne de déploiement qui n'a plus accès au cluster :
| Code | Raison | Ce qui s'est passé |
|---|---|---|
| 137 | OOMKilled | Le noyau a tué le processus par SIGKILL, 128 + 9 |
| 1 | Error | L'application s'est arrêtée en erreur, la mémoire n'y est pour rien |
kubectl get pod mon-pod \ -o jsonpath='{.status.containerStatuses[0].state.terminated.exitCode}'Un 137 oriente vers limits.memory ou vers une fuite mémoire ; un
1 oriente vers les journaux de l'application. Confondre les deux fait
augmenter une limite mémoire qui n'était pas en cause.
Solutions :
- Augmentez la limite mémoire
- Surveillez la consommation mémoire pour détecter des fuites éventuelles
- Utilisez Prometheus pour monitorer container_memory_working_set_bytes
Pod Pending : des requests que personne ne peut servir
Section intitulée « Pod Pending : des requests que personne ne peut servir »Le troisième symptôme ne fait ni crasher ni ralentir : le Pod ne démarre
jamais. Des requests supérieures à ce qu'un nœud peut offrir laissent le
scheduler sans candidat, et le Pod reste en Pending indéfiniment.
kubectl describe pod mon-podLe message d'échec nomme la ressource qui manque, nœud par nœud :
0/2 nodes are available: 1 Insufficient cpu, 1 Insufficient memory,1 node(s) had untolerated taint(s).Lisez-le comme un décompte : sur 2 nœuds, aucun ne convient, et le motif
diffère d'un nœud à l'autre. Le mot Insufficient désigne toujours les
requests, jamais les limits : c'est la preuve que le placement se joue sur
ce que le Pod demande, pas sur son plafond.
Éviction : quand Kubernetes fait le ménage
Section intitulée « Éviction : quand Kubernetes fait le ménage »Si un nœud manque de ressources, Kubernetes doit faire de la place pour les Pods les plus importants. Il utilise un mécanisme d'éviction pour supprimer les Pods non prioritaires.
L'ordre d'éviction dépend de la classe de QoS (Quality of Service) de chaque Pod.
Les trois classes de QoS
Section intitulée « Les trois classes de QoS »Kubernetes attribue automatiquement une classe de QoS à chaque Pod en fonction de sa configuration de ressources.
| Classe | Condition | Priorité à l'éviction |
|---|---|---|
| Guaranteed | requests = limits, CPU et mémoire, sur tous les conteneurs | Derniers évincés |
| Burstable | au moins un conteneur avec des requests, sans remplir la condition ci-dessus | Évincés après BestEffort |
| BestEffort | aucun conteneur ne déclare ni requests ni limits | Premiers évincés |
Les mots « tous les conteneurs » ne sont pas une précaution de rédaction, c'est
le piège de cette classification. Un Pod dont le conteneur principal est
parfaitement réglé et dont le sidecar ne déclare rien n'est pas
Guaranteed :
kubectl get pod qos-deux-conteneurs -o jsonpath='{.status.qosClass}'BurstableVous croyez être protégé de l'éviction, vous ne l'êtes pas, et c'est le conteneur oublié qui a fait basculer le Pod entier.
En cas de pression mémoire sur un nœud, Kubernetes évince d'abord les Pods BestEffort, puis les Burstable, et en dernier recours les Guaranteed.
Vérifier la QoS d'un Pod :
kubectl get pod mon-pod -o jsonpath='{.status.qosClass}'Configurer les ressources selon le workload
Section intitulée « Configurer les ressources selon le workload »Il n'existe pas de valeur universellement bonne : le réglage dépend de ce que vous protégez. Un service critique veut des garanties, un traitement par lots veut de l'élasticité, un environnement de test veut surtout ne pas gaspiller.
-
Identifier le type de workload
Type de workload QoS recommandée Pourquoi Base de données, API critique Guaranteed Protégé contre l'éviction Serveur web avec pics de charge Burstable Doit pouvoir monter en charge Job batch temporaire Burstable A besoin de plus de ressources si disponible Tâches non critiques BestEffort Peut être arrêté en cas de besoin -
Configurer selon la QoS choisie
Workloads critiques (Guaranteed)
Section intitulée « Workloads critiques (Guaranteed) »Pour les applications critiques (bases de données, APIs essentielles), configurez requests = limits :
resources: requests: cpu: "2" memory: "4Gi" limits: cpu: "2" memory: "4Gi"Workloads élastiques (Burstable)
Section intitulée « Workloads élastiques (Burstable) »Pour les applications qui supportent les variations de charge :
resources: requests: cpu: "250m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi"Cette configuration garantit 250m CPU et 128Mi en permanence, mais autorise jusqu'à 500m CPU et 256Mi en cas de pic.
Workloads non critiques (BestEffort)
Section intitulée « Workloads non critiques (BestEffort) »Pour les tâches qui peuvent être interrompues sans conséquence :
resources: {}Tableau récapitulatif
Section intitulée « Tableau récapitulatif »Ces quatre lignes suffisent à décider dans la plupart des cas. Retenez surtout la colonne de droite : c'est le risque encouru qui doit guider le réglage, pas une valeur recopiée d'un exemple.
| Type d'application | QoS | Requests CPU | Limits CPU | Requests Mémoire | Limits Mémoire |
|---|---|---|---|---|---|
| Base de données, API critique | Guaranteed | 2 CPU | 2 CPU | 4Gi | 4Gi |
| Serveur web | Burstable | 250m | 500m | 128Mi | 256Mi |
| Batch job | Burstable | 500m | 1000m | 512Mi | 1024Mi |
| Pods de test | BestEffort | - | - | - | - |
Dépannage
Section intitulée « Dépannage »Les trois symptômes ci-dessous se distinguent par ce que fait le Pod. Un Pod qui ne démarre pas renvoie aux requests et au placement ; un Pod qui redémarre renvoie à la limite mémoire ; un Pod qui ralentit renvoie à la limite CPU. Identifier lequel des trois vous avez sous les yeux fait l'essentiel du diagnostic.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Pod OOMKilled | Limit mémoire trop basse | Augmenter limits.memory |
| Application lente | Throttling CPU | Augmenter limits.cpu ou supprimer la limit |
Pod Pending, Insufficient cpu ou Insufficient memory | Requests > ressources disponibles | Réduire requests ou ajouter des nœuds |
| Éviction fréquente | QoS BestEffort | Ajouter des requests pour passer en Burstable |
À retenir
Section intitulée « À retenir »- Requests = ressources garanties, utilisées par le scheduler pour placer le Pod
- Limits = plafond maximal, déclenche throttling (CPU) ou OOMKill (mémoire)
- QoS Guaranteed (requests = limits) : pour les workloads critiques
- QoS Burstable (requests < limits) : pour les workloads avec pics de charge
- QoS BestEffort (aucune config) : premiers évincés, à éviter en production
- Le throttling CPU ralentit l'application ; l'OOMKilled la tue
Guaranteedexige requests = limits sur tous les conteneurs, sidecars compriskubectl topréclame metrics-server et ne rend pas de pourcentage- Pour un OOMKill, lisez la colonne
STATUS, oustate.terminated.reasonsi le Pod n'a pas redémarré
Contrôle des connaissances
Section intitulée « Contrôle des connaissances »Sept questions sur ce qui coûte le plus cher : la différence entre
garantie et plafond, la condition exacte de la classe Guaranteed, et ce
qui distingue le bridage CPU de l'arrêt pour dépassement mémoire.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Scheduling avancé : L'influence directe des requests sur le placement des Pods par le scheduler.
- Horizontal Pod Autoscaler (HPA) : Le scaling automatique du nombre de réplicas, calculé à partir des requests déclarées.
- Vertical Pod Autoscaler (VPA) : L'ajustement automatique des requests et des limits à partir de la consommation réelle.