L’article sur les requests et limits explique comment un pod correctement dimensionné se comporte. Rien dans cette mécanique n’empêche une équipe d’en déployer mille, chacun parfaitement dimensionné individuellement, jusqu’à épuiser toute la capacité du cluster au détriment des autres équipes. ResourceQuota et LimitRange répondent à une question différente : pas « ce pod est-il bien dimensionné » mais « combien un namespace entier a-t-il le droit de consommer ».
ResourceQuota : un plafond agrégé par namespace
Une ResourceQuota limite la somme des ressources demandées ou consommées par tous les objets d’un namespace, pas un objet individuel.
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-payments-quota
namespace: payments
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "50"
Une fois cette quota posée, chaque nouveau pod créé dans le namespace payments doit déclarer des requests explicites : sans cette déclaration, la création de l’objet est rejetée directement par l’API server, pas seulement avertie. C’est un effet de bord souvent découvert par surprise : poser une ResourceQuota sur un namespace où des pods tournaient déjà sans requests explicites bloque tout nouveau déploiement tant que chaque pod n’est pas corrigé.
LimitRange : des valeurs par défaut et des bornes
Là où ResourceQuota plafonne un agrégat, LimitRange agit pod par pod, container par container, au moment de sa création : il injecte des valeurs par défaut à ce qui n’en déclare pas, et rejette ce qui dépasse un plafond individuel.
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: payments
spec:
limits:
- default:
cpu: "500m"
memory: 512Mi
defaultRequest:
cpu: "250m"
memory: 256Mi
max:
cpu: "2"
memory: 2Gi
type: Container
Ce LimitRange résout précisément le piège mentionné plus haut : un pod créé sans requests explicites reçoit automatiquement 250m/256Mi, ce qui satisfait l’exigence de la ResourceQuota sans que le développeur n’ait eu à y penser. Les deux mécanismes se combinent naturellement : LimitRange comble les oublis individuels, ResourceQuota plafonne l’agrégat qui en résulte.
Le piège du plafond jamais révisé
Une ResourceQuota posée une fois au lancement d’un namespace, jamais reconsidérée, devient soit un plafond artificiel qui bloque une croissance légitime de l’équipe, soit une limite tellement large qu’elle ne protège plus rien. La quota doit se réviser avec la même discipline que n’importe quel budget : périodiquement, contre l’usage réel observé (kubectl describe resourcequota donne la consommation actuelle face au plafond), pas fixée une fois et oubliée.
Le lien avec le multi-tenant
Ces deux mécanismes sont la contrepartie technique de l’isolation décrite dans l’article sur le GitOps à l’échelle : un AppProject restreint quels namespaces une équipe peut cibler, ResourceQuota et LimitRange restreignent ce qu’elle peut y consommer une fois le déploiement autorisé. L’isolation de périmètre sans plafond de consommation laisse une équipe légitimement autorisée à déployer épuiser malgré tout la capacité partagée de tout le cluster.
À retenir
ResourceQuota plafonne la consommation agrégée d’un namespace, LimitRange injecte des valeurs par défaut et borne chaque conteneur individuellement, et les deux se combinent pour éviter qu’un oubli de requests ne devienne soit un rejet à la création, soit une consommation débridée. Poser cette gouvernance par namespace, avec une révision périodique, fait partie du socle multi-équipes d’une migration Kubernetes qui dépasse une seule application.