Introduction
La planification des capacités d'un déploiement Kubernetes consiste à estimer et à configurer le CPU, la mémoire et le nombre de réplicas dont vos charges de travail ont besoin pour fonctionner de manière fiable sans gaspiller d'infrastructure. Chaque déploiement que vous créez consomme des ressources du cluster. Si vous définissez des requests et des limits trop basses, les pods peuvent être évincés ou limités en cas de charge. Si vous les définissez trop hautes, vous surprovisionnez, ce qui augmente les coûts et prive d'autres charges de travail de ressources. Une approche structurée sépare l'estimation, la configuration et la vérification, ce qui réduit les conjectures et les retouches. Ce guide présente une méthode pratique avec des commandes et des exemples concrets.
Vous apprendrez à inventorier votre cluster, à choisir des valeurs de départ sûres, à observer l'utilisation réelle, à configurer l'autoscaling, à diagnostiquer les pannes et à maintenir une liste de contrôle reproductible. L'approche fonctionne pour les services web sans état, les API et les charges de travail similaires. À la fin, vous serez en mesure de dimensionner les déploiements avec confiance et d'éviter les pannes courantes liées aux ressources.
Inventaire des versions et de l'environnement
Avant de définir des paramètres de capacité, confirmez votre version de Kubernetes et les ressources API disponibles. Les champs liés à la capacité comme requests, limits et le comportement de l'autoscaling ont évolué au fil des versions. Exécutez ces commandes sur un cluster avec un accès kubectl :
kubectl version --short
kubectl api-resources | grep -E 'deployments|horizontalpodautoscalers|resourcequotas'
La sortie attendue montrera vos versions client et serveur, puis une liste de groupes API pertinents. Par exemple, sur Kubernetes 1.28 :
Client Version: v1.28.2
Server Version: v1.28.4
deployments apps/v1
horizontalpodautoscalers autoscaling/v2
resourcequotas v1
Si vous utilisez un service Kubernetes managé, la version peut apparaître dans la console cloud. Notez la version mineure exacte car les champs HPA v2 diffèrent de v1. Vérifiez également que l'API des métriques est disponible si vous prévoyez d'autoscaler sur le CPU ou la mémoire :
kubectl get --raw /apis/metrics.k8s.io/v1beta1 | head -n 5
Vous devriez voir une liste de ressources, pas une erreur 404. Si l'API des métriques est absente, installez le metrics-server ou l'équivalent de votre fournisseur. Pour la planification des capacités, vous devez aussi connaître la capacité des nœuds et la pression existante sur les ressources :
kubectl describe nodes | grep -A 5 'Allocated resources'
La sortie montre les requests et limits de CPU et de mémoire en pourcentages. Utilisez cela pour évaluer la marge de manœuvre. Si les nœuds sont déjà demandés à plus de 80 %, évitez d'ajouter de grands déploiements sans étendre le cluster. Documentez ces versions et ces chiffres avant de continuer ; ils influencent la façon dont vous interprétez les métriques et configurez l'autoscaling.
Chemin de configuration sûr
Commencez la planification des capacités avec un seul déploiement et des estimations prudentes. N'essayez pas de dimensionner tous les services à la fois. Un pilote étroit vous permet d'observer l'utilisation réelle et de vous ajuster sans risquer la production. Nous allons créer un déploiement d'application web simple avec des requests et des limits explicites, puis le faire évoluer manuellement et via HPA. Le responsable de ce dimensionnement initial est le responsable technique du service, qui devra revoir ces valeurs après la première semaine de trafic de production et mensuellement par la suite.
Étape 1 : Commencer avec un manifeste de base
Supposons que vous ayez une application web sans état qui utilise typiquement 100 millicores (0,1 CPU) et 128 Mio de mémoire par instance sous charge légère. Le pic peut tripler cela. Définissez les requests initiales sur l'utilisation typique et les limits sur le pic attendu. Créez web-deployment.yaml :
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.25
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "300m"
memory: "256Mi"
Appliquez-le :
kubectl apply -f web-deployment.yaml
Résultat attendu :
deployment.apps/web-app created
Vérifiez les pods :
kubectl get pods -l app=web
Vous devriez voir deux pods en cours d'exécution après quelques secondes. Les requests garantissent que chaque pod obtient au moins les ressources spécifiées. Les limits plafonnent la quantité qu'il peut consommer en pointe. Si le pod dépasse sa limite de mémoire, il est tué par OOM. S'il dépasse sa limite de CPU, il est limité (throttling). C'est pourquoi les limites ne doivent pas être fixées arbitrairement hautes : le throttling peut dégrader la latence avant que vous ne le remarquiez.
Étape 2 : Observer l'utilisation réelle avant de scaler
Laissez le déploiement s'exécuter sous un trafic réaliste pendant quelques heures ou jours. Surveillez la consommation de ressources par pod :
kubectl top pods -l app=web
Exemple de sortie :
NAME CPU(cores) MEMORY(bytes)
web-app-6b4d8c9f5-abcde 45m 102Mi
web-app-6b4d8c9f5-fghij 52m 118Mi
Ce sont des échantillons d'utilisation réelle. Si l'utilisation typique est bien inférieure aux requests, vous pouvez réduire les requests pour améliorer le bin packing. Si elle approche des limites, augmentez les limites ou le nombre de réplicas. Pour une moyenne rapide sur 5 minutes, utilisez kubectl top pods --containers pour un détail par conteneur. Enregistrez ces valeurs ; elles informent l'étape suivante.
Étape 3 : Configurer l'Horizontal Pod Autoscaler (HPA)
L'autoscaling basé sur le CPU ou la mémoire est le principal mécanisme réactif de capacité. Créez un HPA ciblant 60 % d'utilisation CPU moyenne sur les pods :
kubectl autoscale deployment web-app --cpu=60% --min=2 --max=8
Résultat attendu :
horizontalpodautoscaler.autoscaling/web-app autoscaled
Vérifiez le HPA :
kubectl get hpa web-app
Exemple de sortie :
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web-app Deployment/web-app 10%/60% 2 8 2 5m
La colonne TARGETS montre l'utilisation actuelle par rapport à la cible. Attendez quelques minutes et répétez s'il n'y a pas de charge. Pour simuler une charge, vous pouvez temporairement exécuter un pod générateur de charge. Cependant, ne vous fiez pas uniquement au HPA ; il réagit après coup. Définissez un nombre minimum de réplicas raisonnable pour la charge de base afin d'éviter les démarrages à froid.
Étape 4 : Ajuster les requests et limits de manière itérative
Une fois que vous avez des métriques, ajustez le manifeste. Supposons que le pod moyen utilise 80m de CPU et 150 Mio de mémoire en pic. Vos limites d'origine étaient trop basses ; augmentez-les à 500m de CPU et 512 Mio de mémoire, mais gardez les requests à 100m et 128 Mio pour éviter de sur-réserver. Mettez à jour le déploiement :
kubectl patch deployment web-app -p '{"spec":{"template":{"spec":{"containers":[{"name":"web","resources":{"limits":{"cpu":"500m","memory":"512Mi"}}}]}}}}'
Cela déclenche une mise à jour progressive. Surveillez le déploiement :
kubectl rollout status deployment/web-app
Résultat attendu :
deployment "web-app" successfully rolled out
Revérifiez l'utilisation et le HPA. Cette boucle itérative est au cœur de la planification des capacités. Le responsable technique doit revoir ces paramètres chaque semaine pendant le premier mois, puis mensuellement, ou après tout changement de trafic significatif.
Étape 5 : Envisager l'affinité de nœud et les Pod Disruption Budgets (optionnel)
La planification des capacités inclut aussi la disponibilité. Si votre déploiement ne doit pas avoir tous ses réplicas sur un seul nœud, utilisez l'anti-affinité de pod. Par exemple, pour répartir les pods sur les nœuds, ajoutez ceci à la spécification du pod :
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
De plus, définissez un PodDisruptionBudget (PDB) pour limiter les perturbations volontaires pendant la maintenance. Exemple de PDB :
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: web
Appliquez avec kubectl apply -f pdb.yaml. Cela garantit qu'au moins un pod reste disponible pendant les drains de nœuds. L'équipe plateforme possède les politiques de PDB et les revoit trimestriellement.
Vérification et diagnostics
Après la configuration, vérifiez que les paramètres de capacité sont efficaces et que le système se comporte comme prévu sous charge. Utilisez plusieurs signaux d'observabilité.
Vérifier les requests et limits de ressources
kubectl get deployment web-app -o json | jq '.spec.template.spec.containers[0].resources'
Résultat attendu :
{
"limits": {
"cpu": "500m",
"memory": "512Mi"
},
"requests": {
"cpu": "100m",
"memory": "128Mi"
}
}
Vérifier le statut et les événements du HPA
kubectl describe hpa web-app
Cherchez les événements de mise à l'échelle. Extrait d'exemple :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulRescale 10m horizontal-pod-autoscaler New size: 3; reason: cpu resource utilization (percentage of request) above target
Si vous voyez des mises à l'échelle rapides et répétées, vérifiez le flapping causé par des seuils trop bas ou des métriques bruitées. Ajustez la cible ou ajoutez des fenêtres de stabilisation comme décrit plus loin.
Test de charge pour confirmer la mise à l'échelle
Générez de la charge à l'aide d'un pod temporaire avec un outil de charge HTTP simple. Par exemple, exécutez hey depuis un conteneur de débogage :
kubectl run load-generator --image=williamyeh/hey --rm -it -- -n 10000 -c 10 http://web-app-service/
Surveillez le HPA et le nombre de pods pendant le test :
watch kubectl get hpa, pods
Après le test, vérifiez que le nombre de réplicas est redescendu au minimum une fois la charge arrêtée. Cela confirme que le HPA réduit correctement l'échelle. Le propriétaire du service doit exécuter un tel test avant toute version majeure ou événement de trafic.
Diagnostiquer les problèmes de capacité
Si des pods sont en attente, vérifiez les ressources des nœuds :
kubectl describe pod <pod-name> | grep -A 3 Events
Un événement courant est 0/2 nodes are available: 2 Insufficient cpu. Cela indique que le cluster manque de capacité pour le CPU demandé. Vous devez soit réduire les requests, ajouter des nœuds, soit réduire d'autres charges de travail. Si des pods sont tués par OOM, inspectez la raison de terminaison :
kubectl get pod <pod-name> -o json | jq '.status.containerStatuses[0].state.terminated.reason'
La sortie OOMKilled signifie que la limite de mémoire était trop basse. Augmentez la limite ou corrigez la fuite de l'application. Utilisez kubectl describe node pour voir la pression mémoire. Ces étapes de diagnostic doivent être documentées dans votre runbook pour les ingénieurs d'astreinte.
Modes de défaillance et récupération
La planification des capacités peut mal tourner de plusieurs façons. Connaître les défaillances courantes et comment les récupérer est essentiel. Chaque mode de défaillance ci-dessous liste un propriétaire désigné qui doit être alerté et l'action de récupération typique.
OOMKilled et évictions de pods
Défaillance : Les pods dépassent les limites de mémoire et sont tués, provoquant des redémarrages et des interruptions potentielles.
Détection : kubectl get pods montre RESTARTS qui augmente, et kubectl describe pod montre OOMKilled.
Récupération : Augmentez temporairement les limites de mémoire, mais recherchez la cause. Si l'application a besoin de plus de mémoire en pic, ajustez les limites et éventuellement les requests. Par exemple, pour définir la limite de mémoire à 1 Gio :
kubectl set resources deployment web-app --limits=memory=1Gi
Vérifiez ensuite avec kubectl rollout status. Si l'application a une fuite de mémoire, corriger le code est la solution à long terme. Le développeur de l'application est propriétaire de l'utilisation de la mémoire et doit être alerté dès le premier événement OOMKilled.
Throttling CPU causant une latence élevée
Défaillance : Les limites de CPU sont trop basses ; les pods sont limités mais pas tués, ce qui entraîne des réponses lentes.
Détection : Vérifiez les métriques de conteneur pour container_cpu_cfs_throttled_seconds_total, ou corrélez une latence élevée avec les atteintes de limite CPU dans votre tableau de bord de surveillance.
Récupération : Augmentez les limites de CPU. Par exemple :
kubectl set resources deployment web-app --limits=cpu=1
Surveillez la latence après le changement. Le SRE d'astreinte doit effectuer cette récupération, puis planifier une revue de capacité avec le propriétaire du service.
Épuisement des ressources du nœud et pods en attente
Défaillance : Les nœuds manquent de CPU ou de mémoire allouable, de sorte que les nouveaux pods ne peuvent pas être planifiés.
Détection : kubectl get pods montre l'état Pending ; kubectl describe node montre une pression élevée sur les ressources.
Récupération : Réduisez les requests de ressources pour les déploiements non critiques, ajoutez des nœuds ou utilisez l'autoscaler de cluster s'il est disponible. Pour réduire temporairement les requests :
kubectl set resources deployment web-app --requests=cpu=50m,memory=64Mi
Cela peut affamer les pods en cas de mauvaise utilisation, alors ne le faites que lorsque vous comprenez la charge de travail. L'administrateur du cluster possède la capacité des nœuds et doit être notifié lorsque la pression dépasse 80 %.
Mauvaise configuration du HPA causant du flapping
Défaillance : L'utilisation cible du HPA est trop basse ou les métriques sont bruitées, provoquant des mises à l'échelle rapides en montée et en descente, déstabilisant le service.
Détection : Les événements HPA montrent des SuccessfulRescale fréquents avec des tailles alternées.
Récupération : Ajustez le pourcentage cible ou ajoutez une fenêtre de stabilisation. Par exemple, pour définir la stabilisation de réduction à 5 minutes :
kubectl patch hpa web-app --type='json' -p='[{"op": "replace", "path": "/spec/behavior/scaleDown/stabilizationWindowSeconds", "value": 300}]'
Vérifiez avec kubectl get hpa web-app -o yaml. Le propriétaire du service doit revoir les paramètres HPA mensuellement et après tout changement de modèle de trafic.
Rollback d'un mauvais changement de capacité
Si un changement cause des problèmes, annulez le déploiement à la révision précédente :
kubectl rollout undo deployment/web-app
Cela revient à la dernière configuration connue comme bonne. Vérifiez le statut du déploiement. Pour revenir à une révision spécifique, listez d'abord les révisions :
kubectl rollout history deployment/web-app
Puis utilisez --to-revision=<n>. Le gestionnaire de version possède les décisions de rollback et doit documenter l'incident.
Pièges courants et comment les éviter
Au-delà des modes de défaillance, plusieurs pratiques piègent fréquemment les équipes. Reconnaître ces pièges tôt permet d'économiser du temps et des ressources.
Définir des requests et limits trop proches
Pourquoi cela arrive : Les équipes copient les valeurs de production vers le développement sans ajuster pour un trafic plus faible, ou elles définissent les deux à la même valeur élevée pour éviter le throttling.
Conséquence : La sur-réservation gaspille la capacité du cluster et conduit à un mauvais bin packing, augmentant les coûts.
Comment éviter : Basez les requests sur l'utilisation moyenne réelle mesurée avec kubectl top, et les limites sur l'utilisation de pointe plus une marge de sécurité de 20 à 30 %. Revoyez mensuellement.
Ignorer la capacité et la topologie des nœuds
Pourquoi cela arrive : Les développeurs se concentrent sur les limites au niveau des pods et oublient que les nœuds ont des ressources finies.
Conséquence : Les pods peuvent être non planifiables même si le cluster semble avoir des ressources libres si les requests sont déséquilibrées.
Comment éviter : Utilisez régulièrement kubectl describe nodes pour vérifier Allocated resources. Envisagez l'affinité et l'anti-affinité de nœud pour répartir la charge. Alertez lorsque les requests des nœuds dépassent 70 %.
Trop compter sur le HPA sans réplicas minimum
Pourquoi cela arrive : Les équipes supposent que le HPA gérera toute la mise à l'échelle, y compris depuis zéro, mais le HPA ne scale que sur la base de la charge actuelle et peut être lent à réagir aux pics soudains.
Conséquence : Démarrages à froid et trafic abandonné pendant les pics de trafic.
Comment éviter : Définissez un nombre minimum de réplicas capable de gérer le trafic de base plus une marge. Utilisez des requests CPU burstable pour permettre des pics sans throttling. Le propriétaire du service doit définir ce minimum.
Ne pas surveiller l'utilisation réelle après le déploiement
Pourquoi cela arrive : Après le déploiement avec des estimations initiales, les équipes passent à la tâche suivante.
Conséquence : Les paramètres de ressources deviennent obsolètes, conduisant à un sur ou sous-provisionnement.
Comment éviter : Établissez une cadence de revue (mensuelle) et utilisez des tableaux de bord automatisés pour suivre les tendances d'utilisation des ressources. Le responsable d'ingénierie possède ce processus.
Utiliser les quotas de ressources comme un instrument brutal
Pourquoi cela arrive : Les administrateurs définissent des quotas serrés pour contrôler les coûts, mais ils restreignent les charges de travail légitimes.
Conséquence : Les déploiements échouent à se planifier, frustrant les développeurs.
Comment éviter : Coordonnez les quotas avec les plans de capacité réels. Revoyez l'utilisation des quotas mensuellement et ajustez en fonction de la croissance projetée. L'équipe plateforme possède la politique de quotas.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour revoir la capacité de tout déploiement Kubernetes avant et après les changements. Le propriétaire du service est responsable de chaque élément ; le responsable d'ingénierie revoit la liste complétée mensuellement.
| Élément | Commande ou vérification | Résultat attendu |
|---|---|---|
| Version du cluster et API des métriques disponible | kubectl version --short, kubectl get --raw /apis/metrics.k8s.io/v1beta1 | Version serveur >= 1.20, le point de terminaison des métriques renvoie une liste de ressources |
| Marge de capacité des nœuds | kubectl describe nodes | grep -A 5 'Allocated resources' | Requests CPU et mémoire inférieures à 70 % en moyenne |
| Le déploiement a des requests et des limits | kubectl get deployment <name> -o json | jq '.spec.template.spec.containers[0].resources' | Les requests et limits sont définies pour le CPU et la mémoire |
| HPA configuré avec min/max et cible raisonnables | kubectl get hpa <name> | Min replicas >= 2, max <= capacité du nœud, cible 50-80 % |
| Utilisation réelle dans les limites | kubectl top pods -l app=<label> | Utilisation mémoire inférieure à 80 % de la limite, throttling CPU minimal |
| Pas de pods en attente ou en crash-loop | kubectl get pods -l app=<label> | Tous les pods en cours d'exécution, pas de redémarrages |
| Plan de rollback connu | kubectl rollout history deployment/<name> | Au moins une révision précédente disponible |
| PodDisruptionBudget en place si nécessaire | kubectl get pdb | PDB existe avec minAvailable ou maxUnavailable |
| Comportement de mise à l'échelle testé | Test de charge + watch kubectl get hpa, pods | Le HPA monte en charge et redescend après |
| Documentation mise à jour avec les décisions de capacité | Wiki d'équipe ou runbook | Requests, limites et justification de mise à l'échelle actuelles enregistrées |
Parcourez cette liste de contrôle lors du déploiement initial, après des changements de trafic, et périodiquement (par exemple, mensuellement).
Conclusion
La planification des capacités d'un déploiement Kubernetes est un processus continu, pas une tâche ponctuelle. Commencez par un manifeste de base définissant des requests et des limits prudentes. Utilisez kubectl top et les événements HPA pour observer le comportement réel. Ajustez de manière itérative et vérifiez toujours avec des commandes et des tests de charge. En cas de défaillance, sachez détecter et récupérer rapidement. Utilisez la liste de contrôle opérationnelle pour revoir régulièrement la capacité. En suivant ces étapes pratiques, vous réduisez le risque de pannes liées aux ressources et gardez votre cluster efficace. Commencez par un petit déploiement, mesurez, puis étendez votre processus à d'autres charges de travail. La planification des capacités est un élément clé pour exploiter Kubernetes de manière fiable.