
Gérer les ressources au niveau du Namespace : ResourceQuotas et LimitRanges
Apprenez à utiliser ResourceQuotas et LimitRanges dans Kubernetes pour contrôler et limiter la consommation de ressources au niveau des Namespaces.
Au-delà du Pod : la gouvernance des ressources à l'échelle du Namespace
Après avoir appris à définir les requêtes et limites pour des conteneurs individuels et compris l'impact des classes de QoS, nous allons maintenant élever notre perspective. Dans les environnements multi-locataires ou partagés, où plusieurs équipes ou projets coexistent au sein d'un même cluster Kubernetes, il devient essentiel de pouvoir contrôler la consommation globale des ressources au niveau du Namespace. Comment s'assurer qu'une équipe ne monopolise pas toutes les ressources du cluster ? Comment garantir une allocation équitable ou imposer des bonnes pratiques de définition des ressources pour tous les Pods d'un projet ?
Kubernetes propose deux outils puissants pour répondre à ces besoins de gouvernance administrative : ResourceQuotas et LimitRanges. Ces objets d'API permettent aux administrateurs de cluster de définir des politiques et des contraintes qui s'appliquent à l'ensemble d'un Namespace, complétant ainsi la gestion fine au niveau du Pod.
Ce chapitre explore comment utiliser ces deux mécanismes pour établir des budgets de ressources, imposer des limites par défaut et valider les spécifications des Pods, contribuant ainsi à une utilisation plus contrôlée, équitable et prévisible des ressources du cluster.
ResourceQuotas : définir les budgets globaux du Namespace
Un objet ResourceQuota permet de définir des limites sur la quantité totale de ressources qui peuvent être consommées par l'ensemble des objets présents dans un Namespace donné. Il agit comme un budget global pour ce Namespace.
Les quotas peuvent porter sur différentes catégories de ressources :
- Ressources de calcul : Quantité totale de CPU et de mémoire pouvant être demandée (
requests.cpu,requests.memory) ou limitée (limits.cpu,limits.memory) par tous les Pods du Namespace. - Ressources de stockage : Quantité totale de stockage persistant pouvant être demandée via les PersistentVolumeClaims (
requests.storage), ou nombre total de PVCs (persistentvolumeclaims). On peut aussi définir des quotas par StorageClass (ex:fast-ssd.storageclass.storage.k8s.io/requests.storage). - Nombre d'objets : Nombre maximum d'objets d'un certain type pouvant exister dans le Namespace (ex:
pods,services,replicationcontrollers,secrets,configmaps,deployments.apps,jobs.batch, etc.). - Ressources étendues : Quotas pour des ressources spécifiques comme les GPU (ex:
requests.nvidia.com/gpu).
Lorsqu'une ResourceQuota est définie pour un Namespace, Kubernetes active un contrôleur d'admission. Avant de créer ou de modifier un objet (Pod, Service, PVC...), ce contrôleur vérifie si l'action respecte les quotas définis. Si la création de l'objet entraînait le dépassement d'un quota, l'opération est rejetée.
Exemple de ResourceQuota : Limiter un namespace 'dev-team-alpha' à 10 CPU de request, 20 Gi de mémoire de request, 10 Pods et 5 Services.
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources-quota
namespace: dev-team-alpha
spec:
hard:
requests.cpu: "10" # Total CPU requests ne peut pas dépasser 10 coeurs
requests.memory: "20Gi" # Total Memory requests ne peut pas dépasser 20 GiB
limits.cpu: "20" # Total CPU limits ne peut pas dépasser 20 coeurs
limits.memory: "40Gi" # Total Memory limits ne peut pas dépasser 40 GiB
pods: "10" # Maximum 10 Pods dans le namespace
services: "5" # Maximum 5 Services
Une conséquence importante de l'activation d'une ResourceQuota pour les ressources de calcul (CPU/mémoire) est que tous les Pods créés dans ce Namespace doivent avoir des requests et limits définis pour ces ressources. Sinon, le contrôleur d'admission rejettera leur création car il ne peut pas vérifier le respect du quota. C'est là que les LimitRanges deviennent particulièrement utiles.
LimitRanges : définir les contraintes par objet dans le Namespace
Tandis que ResourceQuota impose des limites agrégées, un objet LimitRange permet de définir des contraintes sur les ressources demandées par des objets individuels (principalement Pods et Conteneurs, mais aussi PVCs) au sein d'un Namespace. Il permet d'imposer des bonnes pratiques ou des valeurs par défaut.
Un LimitRange peut spécifier plusieurs types de contraintes par type d'objet (Container, Pod, PersistentVolumeClaim) :
- Default Request (
defaultRequest) : Si un conteneur est créé sans spécifier de request pour une ressource (CPU ou mémoire), cette valeur par défaut lui sera automatiquement assignée. - Default Limit (
default) : Si un conteneur est créé sans spécifier de limite pour une ressource, cette valeur par défaut lui sera assignée. - Max Limit/Request Ratio (
maxLimitRequestRatio) : Impose un ratio maximum entre la limite et la requête pour une ressource dans un conteneur (ex: la limite mémoire ne peut pas être plus de 4 fois supérieure à la requête mémoire). - Max (
max) : Définit la limite maximale autorisée pour une ressource pour un conteneur ou un Pod. - Min (
min) : Définit la requête minimale autorisée pour une ressource pour un conteneur ou un Pod.
Comme ResourceQuota, LimitRange est appliqué par un contrôleur d'admission. Celui-ci peut muter (modifier) les spécifications des Pods pour appliquer les valeurs par défaut, et valider que les valeurs spécifiées respectent les contraintes min/max et de ratio.
Exemple de LimitRange : Dans le namespace 'staging', assigner par défaut 100m CPU / 256Mi de mémoire aux conteneurs sans spécification, et imposer des limites max.
apiVersion: v1
kind: LimitRange
metadata:
name: resource-limits
namespace: staging
spec:
limits:
- type: Container # S'applique aux conteneurs individuellement
max:
cpu: "2" # Limite CPU max par conteneur : 2 coeurs
memory: "1Gi" # Limite mémoire max par conteneur : 1 GiB
min:
cpu: "50m" # Request CPU min par conteneur : 50 millicores
memory: "64Mi" # Request mémoire min par conteneur : 64 MiB
default:
cpu: "200m" # Limite CPU par défaut si non spécifiée
memory: "512Mi" # Limite mémoire par défaut si non spécifiée
defaultRequest:
cpu: "100m" # Request CPU par défaut si non spécifiée
memory: "256Mi" # Request mémoire par défaut si non spécifiée
maxLimitRequestRatio:
cpu: 10 # Ratio limite/requête max pour CPU
memory: 4 # Ratio limite/requête max pour mémoire
Grâce à `defaultRequest` et `default`, un LimitRange permet de satisfaire l'exigence de ResourceQuota qui impose que tous les Pods aient des requests/limits définis, même si l'utilisateur ne les spécifie pas explicitement.
Synergie et utilisation conjointe
ResourceQuotas et LimitRanges sont souvent utilisés conjointement pour une gouvernance complète des ressources d'un Namespace :
- ResourceQuota définit le budget global du Namespace (combien de ressources au total peuvent être consommées).
- LimitRange définit les règles pour les objets individuels (quelles sont les tailles min/max autorisées, quelles valeurs par défaut appliquer).
Par exemple, vous pouvez utiliser une ResourceQuota pour limiter la mémoire totale d'un Namespace à 100Gi, et un LimitRange dans ce même Namespace pour vous assurer qu'aucun conteneur ne demande plus de 4Gi et que chaque conteneur a au moins une requête et une limite par défaut s'il n'est pas spécifié.
La mise en place de ces politiques nécessite une bonne compréhension des besoins des applications hébergées et une communication avec les utilisateurs des Namespaces. Il est souvent judicieux de commencer avec des quotas et limites assez larges, de surveiller la consommation réelle, puis d'ajuster progressivement les valeurs pour optimiser l'utilisation des ressources sans bloquer inutilement les utilisateurs.
En conclusion, ResourceQuotas et LimitRanges fournissent aux administrateurs Kubernetes des outils essentiels pour contrôler l'allocation et la consommation des ressources au niveau du Namespace, améliorant ainsi la stabilité, l'équité et la prévisibilité dans les clusters partagés.