Introduction
La planification de la capacité des espaces de noms (namespaces) Kubernetes répond à une question simple : quelle quantité de CPU, de mémoire et d’objets un namespace peut-il consommer avant de risquer la stabilité du cluster ou de priver les autres locataires ? Sans planification délibérée, un seul namespace peut épuiser la capacité des nœuds, déclencher des évictions ou limiter silencieusement les charges de travail. Ce guide offre aux développeurs, consultants DevOps et équipes techniques de startups un processus reproductible et vérifiable pour dimensionner les namespaces, appliquer des quotas et passer à l’échelle en toute sécurité.
Nous nous concentrons sur quatre primitives : le dimensionnement des namespaces, les quotas de ressources (Resource Quotas), les plages de limites (Limit Ranges) et les flux de mise à l’échelle. Chaque section passe de l’observation à l’intervention, puis à la vérification. Vous apprendrez quelles commandes exécuter, quel résultat attendre et comment récupérer lorsqu’une contrainte est violée. Le flux suppose un cluster Kubernetes fonctionnel (v1.24 ou ultérieur pour un comportement stable des quotas et plages de limites) et kubectl configuré avec les permissions appropriées.
La sécurité opérationnelle est primordiale : observer avant de modifier, limiter le rayon d’impact, utiliser des valeurs factices plutôt que des secrets dans les exemples, vérifier le résultat et documenter les chemins de récupération. Tous les exemples sont exécutables sur un cluster local tel que kind ou minikube.
Inventaire de la version et de l’environnement
Les décisions de planification de capacité dépendent de la version de Kubernetes et du modèle de ressources utilisé. Commencez par collecter un inventaire en lecture seule du cluster et du namespace cible. Cela établit le rayon d’impact avant tout changement.
Vérifier la version de Kubernetes
kubectl version --short
Un résultat attendu ressemble à :
Client Version: v1.27.3
Kustomize Version: v5.0.1
Server Version: v1.27.1
Le comportement des Resource Quotas est stable entre les versions, mais les valeurs par défaut des Limit Ranges ont évolué. Par exemple, la possibilité de définir defaultRequest et defaultLimit au niveau du conteneur est disponible depuis les premières versions, mais vérifiez le comportement de votre cluster avec kubectl explain :
kubectl explain limitrange.spec.limits
Si le champ defaultRequest est présent, votre cluster prend en charge les requêtes par défaut au niveau du conteneur. Sinon, vous devrez peut-être effectuer une mise à niveau ou utiliser un webhook d’admission mutationnel.
Inspecter l’état du namespace
Avant de toucher quoi que ce soit, capturez l’état actuel du namespace et sa consommation de ressources :
kubectl get namespace <namespace> -o yaml
kubectl get resourcequota,limitrange -n <namespace>
kubectl top pod -n <namespace> --containers
kubectl top nécessite le metrics-server. S’il est absent, installez-le via :
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Sortie typique pour kubectl top pod :
POD CPU(cores) MEMORY(bytes)
web-5b8f7c9d6-abcde 12m 180Mi
api-7d4f8b9c2-fghij 45m 512Mi
Enregistrez ces valeurs de référence. Elles déterminent si un quota prévu est large ou serré.
Identifier la topologie des charges de travail
Listez les déploiements, statefulsets et daemonsets dans le namespace pour comprendre le comportement de mise à l’échelle :
kubectl get deploy,sts,ds -n <namespace> -o wide
Concentrez-vous sur les requêtes et limites de ressources par charge de travail :
kubectl get deploy -n <namespace> -o=jsonpath='{range .items[*]}{.metadata.name}{" requested="}{.spec.template.spec.containers[*].resources.requests}{" limited="}{.spec.template.spec.containers[*].resources.limits}{"\n"}{end}'
Si de nombreuses charges de travail omettent les requêtes et limites, la planification de la capacité du namespace est impossible. Une Limit Range peut appliquer des valeurs par défaut, ce que nous verrons ensuite.
Chemin de configuration sécurisé
Appliquer des contrôles de capacité sans incident nécessite une approche en couches : d’abord une Limit Range pour définir des valeurs par défaut saines pour les nouveaux pods, puis un Resource Quota pour plafonner la consommation globale, puis une vérification sous trafic réaliste. Le plus petit changement justifié est une seule Limit Range appliquée à un namespace de test.
Étape 1 : Créer un namespace de test
Validez toujours dans un namespace isolé :
kubectl create namespace capacity-test
Étape 2 : Appliquer une Limit Range
Une Limit Range applique des requêtes et limites par défaut pour les conteneurs qui ne les définissent pas explicitement. Elle contraint également les valeurs min/max pour tout pod admis dans le namespace.
Enregistrez sous limit-range.yaml :
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- type: Container
max:
cpu: "1"
memory: "1Gi"
min:
cpu: "50m"
memory: "64Mi"
default:
cpu: "250m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
Appliquez et vérifiez :
kubectl apply -f limit-range.yaml -n capacity-test
kubectl get limitrange -n capacity-test default-limits -o yaml
Observez que la spec est renvoyée avec les valeurs par défaut. Créez maintenant un pod sans ressources explicites :
apiVersion: v1
kind: Pod
metadata:
name: test-pod-defaults
spec:
containers:
- name: nginx
image: nginx:1.25
Après application, inspectez les ressources effectives du pod :
kubectl get pod test-pod-defaults -n capacity-test -o jsonpath='{.spec.containers[0].resources}'
Sortie attendue :
{"limits":{"cpu":"250m","memory":"256Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}
La Limit Range a injecté des valeurs par défaut sûres. Cela empêche qu’un pod soit planifié sans ressources, ce qui pourrait autrement conduire à une éviction imprévisible.
Étape 3 : Appliquer un Resource Quota
Un Resource Quota plafonne le total des requêtes, limites et nombres d’objets dans le namespace. Enregistrez sous resource-quota.yaml :
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-quota
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "6"
limits.memory: "12Gi"
persistentvolumeclaims: "10"
pods: "20"
services: "5"
Appliquez et inspectez l’utilisation actuelle :
kubectl apply -f resource-quota.yaml -n capacity-test
kubectl get resourcequota -n capacity-test namespace-quota -o yaml
Les champs status.hard et status.used montrent le quota par rapport à la consommation actuelle. Au départ, used reflétera le pod créé précédemment :
status:
hard:
limits.cpu: "6"
limits.memory: 12Gi
persistentvolumeclaims: "10"
pods: "20"
requests.cpu: "4"
requests.memory: 8Gi
services: "5"
used:
limits.cpu: 250m
limits.memory: 256Mi
pods: "1"
requests.cpu: 100m
requests.memory: 128Mi
Cela montre qu’un pod consomme 100m de requêtes CPU et 128Mi de requêtes mémoire, laissant une large marge.
Étape 4 : Valider l’application du quota
Déployez une charge de travail qui tente de dépasser le quota. Par exemple, créez un déploiement avec 10 réplicas, chacun demandant 1 CPU :
kubectl create deployment quota-breaker --image=nginx --replicas=10 -n capacity-test
kubectl set resources deployment quota-breaker -n capacity-test --requests=cpu=1,memory=1Gi --limits=cpu=1,memory=1Gi
kubectl rollout status deployment/quota-breaker -n capacity-test
Le déploiement échouera avec des événements tels que :
Error creating: pods "quota-breaker-..." is forbidden: exceeded quota: namespace-quota, requested: requests.cpu=10, used: requests.cpu=100m, limited: requests.cpu=4
Cela prouve que le quota fonctionne. Pour récupérer, réduisez le déploiement :
kubectl scale deployment quota-breaker --replicas=1 -n capacity-test
Confirmez ensuite que l’utilisation du quota revient dans les limites :
kubectl get resourcequota -n capacity-test namespace-quota
Vérification et diagnostic
La vérification pour la planification de capacité comporte deux niveaux : (1) confirmer que les contrôles sont actifs, et (2) mesurer la consommation réelle par rapport à la marge prévue. Cette section fournit des commandes et des sorties attendues pour les deux.
Vérifier l’état des Resource Quotas et Limit Ranges
Exécutez une vérification combinée :
kubectl get resourcequota,limitrange -n capacity-test
Sortie attendue :
NAME AGE
resourcequota/namespace-quota 10m
NAME CREATED AT
limitrange/default-limits 2023-10-01T12:00:00Z
Pour une utilisation détaillée du quota :
kubectl describe resourcequota namespace-quota -n capacity-test
La sortie inclut Used par rapport à Hard pour chaque ressource contrainte. Observez si une ressource approche sa limite (par exemple >80%). Si c’est le cas, vous devez soit augmenter le quota, soit réduire les charges de travail.
Mesurer la consommation réelle
Utilisez kubectl top pour les métriques en direct des pods :
kubectl top pods -n capacity-test --sort-by=cpu
Exemple :
NAME CPU(cores) MEMORY(bytes)
quota-breaker-5b8f7c9d6-abcde 120m 512Mi
test-pod-defaults 2m 45Mi
Comparez ces valeurs aux montants demandés. Un pod qui demande 1 CPU mais n’utilise que 120m est surprovisionné et gonfle inutilement l’utilisation du quota. Ajustez les requêtes en fonction des pics observés, pas du pire cas. Une pratique courante consiste à définir les requêtes au P95 de l’utilisation observée et les limites à 2x les requêtes.
Diagnostiquer les échecs de planification
Si des pods restent en attente (Pending), vérifiez les événements :
kubectl describe pod <pending-pod> -n capacity-test
Recherchez des messages tels que :
Warning FailedScheduling 28s default-scheduler 0/3 nodes are available: 3 Insufficient cpu, 5 Insufficient memory.
Cela indique des contraintes de capacité au niveau des nœuds, pas un quota de namespace. Vérifiez les ressources allouables des nœuds :
kubectl describe nodes | grep -A 5 "Allocatable"
Si le quota du namespace est le blocage, l’événement mentionnera « exceeded quota » comme montré précédemment.
Flux de travail de diagnostic pour les incidents de capacité
- Identifiez le pod ou le déploiement en échec.
- Vérifiez
kubectl describe podpour les événements (quota, plage de limites ou ressources des nœuds). - Vérifiez l’utilisation du quota du namespace :
kubectl describe resourcequota. - Vérifiez la capacité des nœuds :
kubectl describe nodes. - Comparez l’utilisation réelle (
kubectl top) avec les requêtes et limites.
Pour les boucles de crash non liées au quota, utilisez :
kubectl logs <pod-name> -n capacity-test --previous
Modes de défaillance et récupération
Une mauvaise configuration de capacité entraîne des modes de défaillance prévisibles. Pour chacun, nous fournissons le signal, la cause probable et la procédure de récupération.
Défaillance 1 : Pods bloqués en Pending avec « exceeded quota »
Signal : Événement dans kubectl describe pod indiquant forbidden: exceeded quota.
Cause : Les requêtes de ressources agrégées du namespace dépasseraient la limite stricte du Resource Quota.
Options de récupération :
- Réduire les réplicas :
kubectl scale deployment <name> --replicas=N - Diminuer les requêtes de ressources pour la charge de travail (modifier le YAML du déploiement).
- Augmenter le quota du namespace si l’équipe en a la capacité :
kubectl edit resourcequota namespace-quota -n <namespace>et augmenterrequests.cpuourequests.memory.
Vérification : Surveillez kubectl get resourcequota jusqu’à ce que used soit inférieur à hard.
Défaillance 2 : Création de pod rejetée par la Limit Range
Signal : Le pod reste non créé, l’événement indique Forbidden: minimum cpu usage per Container is 50m ou similaire.
Cause : La requête du pod est inférieure au minimum de la Limit Range ou supérieure au maximum.
Récupération : Ajustez les ressources du conteneur du pod pour qu’elles soient dans les bornes min/max, ou modifiez la Limit Range si les limites étaient trop strictes. Réappliquez ensuite le manifeste du pod.
Défaillance 3 : Éviction au niveau des nœuds due à la surallocation
Signal : Des pods sont évincés avec la raison Evicted dans kubectl get pods, et la condition du nœud MemoryPressure ou DiskPressure est True.
Cause : La somme des requêtes des pods dans tous les namespaces dépasse les ressources allouables des nœuds. Kubernetes évince d’abord les pods best-effort et burstable.
Récupération :
- Ajouter de la capacité de nœud (mettre à l’échelle le cluster).
- Définir des requêtes significatives sur tous les pods (la Limit Range aide).
- Réduire la surallocation en augmentant les requêtes, pas les limites.
- Utiliser des classes de priorité pour protéger les charges de travail critiques.
Vérification : Vérifiez kubectl get events --field-selector reason=Evicted et les conditions des nœuds.
Défaillance 4 : Épuisement du quota de PersistentVolumeClaim
Signal : La création de PVC échoue avec exceeded quota: persistentvolumeclaims.
Cause : Le nombre de PVC dans le namespace a atteint la limite du Resource Quota.
Récupération : Supprimez les PVC inutilisés (après sauvegarde) ou augmentez le quota si la capacité de la classe de stockage le permet. Avant de supprimer, assurez-vous qu’aucun pod en cours d’exécution ne référence le PVC.
Résumé du manuel de récupération
| Défaillance | Signal | Action immédiate | Solution à long terme |
|---|---|---|---|
| Quota dépassé | Pod en attente, événements | Réduire ou augmenter le quota | Ajuster les requêtes, prévoir l’utilisation |
| Violation de la Limit Range | Pod rejeté | Ajuster les ressources du pod | Concevoir des politiques autour des besoins réels |
| Éviction de nœud | Pods évincés, pression sur le nœud | Ajouter des nœuds ou réduire la charge | Définir requêtes et limites, utiliser des priorités |
| Quota de PVC épuisé | PVC en attente | Supprimer les PVC obsolètes | Mettre en œuvre un cycle de vie du stockage |
Liste de contrôle opérationnelle
La liste de contrôle suivante transforme la planification de capacité en un processus routinier et vérifiable. Parcourez-la avant et après tout changement significatif.
Liste de contrôle pré-changement
- Capturer l’état du namespace :
kubectl get resourcequota,limitrange -n <namespace> -o yaml > before-state.yaml
- Enregistrer l’utilisation actuelle :
kubectl top pods -n <namespace> --containers > before-usage.txt
Utilisez un script pour comparer les requêtes à l’utilisation réelle (exemple avec bash et awk) :
- Identifier les charges de travail surprovisionnées ou sous-provisionnées :
kubectl top pods -n <namespace> --no-headers | awk '{print $1, $2, $3}'
# Comparez avec kubectl get pods -o jsonpath pour les requêtes.
Déjà enregistrés dans before-state.yaml.
- Sauvegarder les quotas de ressources et les plages de limites :
- Documenter le résultat attendu dans un ticket de changement (par exemple, réduire de 20% les requêtes CPU du namespace).
Liste de contrôle d’exécution du changement
- Appliquez un manifeste à la fois. Vérifiez après chaque.
- Utilisez
kubectl diff -f <manifest>pour prévisualiser les changements avant de les appliquer. - Pour les augmentations de quota, utilisez
kubectl patchpour modifier uniquement le champ spécifique :
kubectl patch resourcequota namespace-quota -n <namespace> --type='json' -p='[{"op": "replace", "path": "/spec/hard/requests.cpu", "value": "8"}]'
- Après application, exécutez
kubectl rollout statuspour les déploiements affectés.
Liste de contrôle de vérification post-changement
- Confirmer la mise à jour du quota :
kubectl get resourcequota -n <namespace> -o yaml. - Vérifier les nouveaux événements :
kubectl get events -n <namespace> --sort-by=.lastTimestamp | tail -20. - Surveiller la planification et la santé des pods pendant au moins 10 minutes.
- Comparer les métriques d’utilisation réelle aux prédictions ; ajuster les requêtes si nécessaire.
- Documenter l’état final dans un fichier sous contrôle de version (par exemple, GitOps).
Test local avant production
Testez toujours les changements de capacité dans un namespace contrôlé d’abord. Par exemple, pour simuler une charge élevée :
kubectl run load-generator --image=busybox --restart=Never -- sh -c "while true; do wget -q -O- http://web-service; sleep 0.01; done"
Observez ensuite si les pods maintiennent leurs performances et si le quota est adéquat. Utilisez kubectl port-forward pour exposer un service localement et exécuter des tests de charge avant d’ajouter un ingress ou un équilibreur de charge.
Conclusion
La planification de la capacité des espaces de noms Kubernetes n’est pas un calcul ponctuel ; c’est une boucle continue d’observation, d’application, de vérification et de récupération. En combinant des Limit Ranges pour des valeurs par défaut saines, des Resource Quotas pour l’isolation des locataires et un flux de travail de diagnostic discipliné, les opérateurs peuvent prévenir les incidents de voisinage bruyant et éviter l’instabilité à l’échelle du cluster.
Commencez petit : créez un namespace de test, appliquez une Limit Range, puis un Resource Quota. Observez comment les pods reçoivent des valeurs par défaut et comment les violations de quota sont signalées. Utilisez les commandes de ce guide comme référence, mais validez toujours par rapport à la version de votre cluster et aux modèles de charge de travail de votre équipe.
Prochaines étapes :
- Instrumentez vos namespaces avec Prometheus et Grafana pour visualiser l’utilisation des quotas au fil du temps.
- Intégrez les vérifications de quota dans votre pipeline CI/CD : avant de déployer, exécutez
kubectl auth can-i create pods --namespace <ns>et une application en mode dry-run. - Adoptez GitOps pour les changements de capacité : stockez les YAML de quota et de plage de limites dans le contrôle de version, et utilisez des outils comme Argo CD ou Flux.
Une planification de capacité fiable rend les défaillances visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu’un incident ne force la décision. Avec les exemples pratiques de cet article, vous pouvez dimensionner, limiter et mettre à l’échelle les espaces de noms Kubernetes en toute confiance.