Projet · Phase 5.11

Kubernetes (11/12) — Resources : requests, limits, QoS

Rien n'empêche un Pod de dévorer tout le CPU/RAM d'un node. On établit un contrat de ressources : requests (ce dont j'ai besoin), limits (mon maximum), et les classes QoS qui décident qui survit sous pression.

⏱ ~1 h 30Niveau avancéPrérequis : Kubernetes (10/12)Pratique · TP
L’idée reçue

« Kubernetes répartit les ressources tout seul, je n’ai rien à déclarer. »

Sans contrat de ressources, un Pod peut consommer tout le CPU et la RAM d’un node, et rien ne garantit qu’il aura de quoi tourner. On déclare donc ce dont chaque Pod a besoin (requests) et son maximum (limits) — et on découvre les classes QoS qui décident qui est protégé sous pression.

À la fin de ce module, tu sauras…

  • Distinguer requests (scheduling) et limits (plafond d’exécution)
  • Lire la classe QoS d’un Pod
  • Passer de BestEffort à Burstable, puis Guaranteed
  • Choisir des valeurs raisonnables sans casser l’appli

01Le concept, en une page

Pour placer les Pods en sécurité, Kubernetes a besoin d’un contrat de ressources :
NotionSensQui l’utilise
requests« ce dont j’ai besoin pour tourner »le scheduler (où placer le Pod)
limits« mon maximum autorisé »le runtime (throttle CPU, OOMKill mémoire)
Comprends requests vs limits, concrètement

Requests = réservation pour le scheduling : si aucun node n’a assez de CPU/RAM libre pour la requête, le Pod reste Pending. Limits = plafond : dépasser le CPU → throttling (l’appli ralentit) ; dépasser la mémoire → OOMKilled (le conteneur est tué). Les limits protègent le node, mais trop basses elles créent de l’instabilité.

02L’état de départ : BestEffort

Expérience 1

Prouver l’absence de contrat

Manipule
kubectl get deploy demo-deploy -o yaml | grep -A3 -i 'resources:'
kubectl describe pod <POD_NAME> | grep -i 'QoS Class'
Observe
resources: {}
QoS Class:   BestEffort
resources: {} = ni requests ni limits. Le Pod est en BestEffort : la classe la moins protégée — la première évincée sous pression.
Comprends les trois classes QoS

BestEffort : aucune requête ni limite → premier évincé. Burstable : requests définies (limits optionnelles ou plus hautes) → protection moyenne. Guaranteed : requests == limits pour CPU et mémoire → protection maximale. La classe est déduite automatiquement de ce que tu déclares.

03Passer à Burstable (requests)

Expérience 2

Ajouter des requests, puis des limits

Manipule
kubectl patch deploy demo-deploy --type='json' -p='[
{"op":"replace","path":"/spec/template/spec/containers/0/resources","value":{
 "requests":{"cpu":"50m","memory":"64Mi"},
 "limits":{"cpu":"200m","memory":"128Mi"}
}}
]'
Manipule
kubectl describe pod <NOUVEAU_POD> | grep -i 'QoS Class'
Observe
QoS Class:   Burstable
Comme requests ≠ limits, la classe est Burstable : le Pod a une réservation minimale (protection moyenne) tout en pouvant « bursté » jusqu’à sa limite.
Comprends les unités : m et Mi

50m = 50 millicores = 0,05 cœur CPU. 64Mi = 64 mébioctets de RAM. Les requests réservent au scheduling, les limits plafonnent à l’exécution. Ici : besoin garanti modeste, plafond plus haut pour absorber les pics.

04Guaranteed (requests == limits)

Expérience 3

La classe la plus protégée

Manipule
kubectl patch deploy demo-deploy --type='json' -p='[
{"op":"replace","path":"/spec/template/spec/containers/0/resources","value":{
 "requests":{"cpu":"100m","memory":"128Mi"},
 "limits":{"cpu":"100m","memory":"128Mi"}
}}
]'
kubectl describe pod <NOUVEAU_POD> | grep -i 'QoS Class'
Observe
QoS Class:   Guaranteed
Avec requests == limits (CPU et mémoire), la classe devient Guaranteed : performance prévisible et priorité maximale sous pression. Mais attention : tu réserves exactement ce que tu plafonnes.
Comprends quand Guaranteed est-il judicieux ?

Guaranteed offre la meilleure priorité d’éviction et une performance stable — idéal pour des composants critiques. Mais c’est plus strict : pas de burst au-delà de la limite, et une mémoire trop basse rend les OOMKills plus probables. Sur un cluster aux ressources serrées (ton cas), attention : trop de Pods Guaranteed avec des requests élevées peuvent laisser des Pods en Pending faute de place. On choisit des valeurs raisonnables.

05Quand ça ne rentre pas : Pending

Expérience 4

Comprendre un Pod bloqué

Si tu demandes plus que ce que les nodes offrent, le Pod reste Pending. Diagnostique :

Manipule
kubectl get pods -o wide
kubectl describe pod <POD_PENDING> | grep -iA2 'Events\|Insufficient'
Observe
Warning  FailedScheduling  ... Insufficient cpu
Le message est explicite : pas assez de CPU disponible pour la requête. La solution : réduire les requests, ou réduire le nombre de replicas — un arbitrage réel de production.
Comprends le lien requests ↔ scheduling

Pending + Insufficient cpu/memory = les requests dépassent la capacité libre. Le scheduler ne place jamais un Pod qu’il ne peut pas satisfaire. C’est la preuve concrète que requests pilote le scheduling. Sur ton cluster à ressources limitées, ce cas est fréquent : dimensionne prudemment.

Ce que tu retiens

Un contrat de ressources protège le cluster : requests (besoin, utilisé par le scheduler) et limits (plafond, appliqué par le runtime). Les classes QoS — BestEffort, Burstable, Guaranteed — déterminent qui survit sous pression. Bien dimensionner, c’est éviter le gaspillage et les Pods bloqués en Pending.

Mini-projet

Un contrat de ressources sain

À faire

  1. Prouve la classe de départ (BestEffort) de demo-deploy.
  2. Ajoute requests + limits, prouve le passage à Burstable.
  3. Mets requests == limits, prouve Guaranteed.
  4. Provoque volontairement un Pending (requests trop hautes) et lis l’événement.
  5. Reviens à des valeurs raisonnables pour ton cluster (ressources limitées).
  6. Documente dans BookStack : requests vs limits, les 3 classes QoS, l’arbitrage Guaranteed.
Fil rouge — Tu maîtrises désormais Kubernetes à la main : déployer, exposer, sécuriser, configurer, surveiller, dimensionner. Mais gérer tous ces manifestes YAML séparément devient lourd. Au dernier module : Helm, pour empaqueter toute une application en un seul artefact réutilisable.

?Auto-évaluation

1. Quelle est la différence entre requests et limits ?

Requests = ce dont le Pod a besoin (utilisé par le scheduler pour le placer) ; limits = son maximum autorisé (throttle CPU, OOMKill mémoire).

2. Qu’est-ce qui distingue la classe Guaranteed ?

requests == limits pour CPU et mémoire. C’est la classe la plus protégée, mais sans burst possible.

3. Pourquoi un Pod peut-il rester Pending à cause des ressources ?

Parce qu’aucun node n’a assez de CPU/RAM libre pour satisfaire ses requests. Le scheduler ne le place pas.

Connecte-toi pour enregistrer ta progression.

Suite → Kubernetes (12/12) — Helm : packaging