## Introduction

La planification de capacité dans Kubernetes commence souvent par un problème : un pod est expulsé, un nœud manque de mémoire ou un déploiement ne peut pas être planifié. Les équipes se précipitent alors pour augmenter les limites ou mettre à l'échelle les réplicas sans connaître la consommation réelle des ressources. Résultat : un gaspillage de dépenses cloud ou des incidents répétés.

Cet article fournit un flux de travail pratique, piloté par commandes, pour la planification de capacité avec kubectl. Il couvre comment inspecter l'utilisation actuelle, définir les requêtes et limites de ressources, choisir des stratégies de mise à l'échelle, vérifier les changements et récupérer en cas de problème. Chaque section inclut des commandes concrètes avec les résultats attendus et les signaux d'échec.

Le public cible est constitué de développeurs, d'ingénieurs DevOps et de SRE qui gèrent des charges de travail Kubernetes et souhaitent passer de décisions réactives à une planification proactive fondée sur des preuves.

## Inventaire de la version et de l'environnement

Avant de modifier quoi que ce soit, connaissez votre environnement. Vérifiez la version de kubectl et la connectivité du cluster.

```bash
kubectl version --short
```

Exemple de sortie :

```
Client Version: v1.27.2
Kustomize Version: v5.0.1
Server Version: v1.26.5
```

Si la version majeure/mineure du client et du serveur diffère de plus d'une version, soyez prudent avec les nouveaux champs d'API. Ensuite, confirmez le contexte et l'espace de noms ciblés.

```bash
kubectl config current-context
kubectl get namespaces
```

Cela évite d'appliquer des changements au mauvais cluster ou espace de noms. Pour la planification de capacité, les composants pertinents sont les Deployments, StatefulSets, DaemonSets et Pods. Identifiez ceux dont les paramètres de ressources sont incertains.

```bash
kubectl get pods -o wide --all-namespaces
```

La sortie montre le placement sur les nœuds, l'état et les redémarrages. Les pods en état `Pending` ou avec de nombreux redémarrages ont probablement des problèmes de capacité.

Vérification pratique : exécutez `kubectl describe pod <nom> -n <namespace>` et recherchez des événements comme `FailedScheduling` avec des messages tels que `0/3 nodes are available: insufficient memory`. Cela indique que la requête actuelle dépasse la capacité disponible des nœuds. Notez cela avant de faire tout changement.

## Chemin de configuration sûr

Les requêtes et limites de ressources sont la base de la planification de capacité. Les requêtes définissent la quantité garantie de CPU et de mémoire qu'un pod peut utiliser, tandis que les limites plafonnent l'utilisation maximale. Sans elles, le planificateur ne peut pas prendre de décisions éclairées et un voisin bruyant peut consommer toutes les ressources du nœud.

Définissez les requêtes en fonction de l'utilisation observée, pas de suppositions. Le moyen le plus fiable est d'utiliser le Vertical Pod Autoscaler (VPA) en mode recommandation ou d'inspecter les métriques. Commencez par vérifier l'utilisation actuelle :

```bash
kubectl top pods -n <namespace>
```

Exemple de sortie :

```
NAME                       CPU(cores)   MEMORY(bytes)
nginx-6c8b449f8f-g9f8q     5m           61Mi
redis-68b8d9d5c9-5j4kp     8m           5Mi
```

Si `kubectl top` échoue avec `Error from server (NotFound): the server could not find the requested resource`, le metrics-server n'est pas installé. Installez-le ou utilisez la surveillance du fournisseur cloud.

Pour une application web typique utilisant environ 50m de CPU et 120Mi de mémoire en charge normale, définissez des requêtes avec une petite marge pour couvrir les pics de démarrage : 100m de CPU et 128Mi de mémoire. Les limites peuvent être plus élevées, par exemple 500m de CPU et 512Mi de mémoire, pour permettre des bursts tout en empêchant une consommation incontrôlée.

Exemple d'extrait de Deployment :

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: app
        image: nginx:1.25
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
```

Appliquez-le avec :

```bash
kubectl apply -f deployment.yaml -n <namespace>
```

Après avoir modifié les ressources, effectuez un redémarrage progressif si nécessaire. Certains changements nécessitent la recréation des pods.

```bash
kubectl rollout restart deployment/web-app -n <namespace>
```

Vérifiez l'état du déploiement :

```bash
kubectl rollout status deployment/web-app -n <namespace>
```

Sortie attendue :

```
deployment "web-app" successfully rolled out
```

Si le déploiement reste bloqué, les pods peuvent ne pas pouvoir être planifiés avec les nouvelles requêtes. Vérifiez les événements et ajustez.

## Vérification et diagnostic

Après avoir appliqué des changements de ressources ou mis à l'échelle, vérifiez que les pods fonctionnent et sont sains. Utilisez les commandes standard :

```bash
kubectl get pods -o wide -n <namespace>
```

Recherchez le statut `Running` et les colonnes `READY` indiquant `1/1`. Pour une inspection plus approfondie :

```bash
kubectl describe pod <nom-du-pod> -n <namespace>
```

Sections clés dans la sortie de describe :
- `Conditions` : `Ready` doit être `True`
- `Containers.State` : doit afficher `Running` sans augmentation du nombre de redémarrages
- `Events` : avertissements sur les problèmes de ressources, par exemple `OOMKilled` si la limite était trop basse

Pour voir l'utilisation réelle des ressources après un changement :

```bash
kubectl top pods -n <namespace>
```

Comparez l'utilisation avec les requêtes et limites. Si l'utilisation est constamment proche des limites, envisagez d'augmenter les limites ou d'optimiser l'application. Si l'utilisation est bien inférieure aux requêtes, vous surprovisionnez et gaspillez de la capacité.

Pour la vérification au niveau de l'application, utilisez `kubectl port-forward` pour accéder à un pod localement :

```bash
kubectl port-forward pod/<nom-du-pod> 8080:80 -n <namespace>
```

Ensuite, ouvrez `http://localhost:8080` dans un navigateur ou utilisez curl.

Si vous avez modifié le nombre de réplicas, vérifiez la répartition de la charge :

```bash
kubectl get endpoints <nom-du-service> -n <namespace>
```

La sortie attendue inclut les adresses IP de tous les pods prêts. Si certains pods manquent dans les endpoints, ils ne sont pas prêts et ne recevront pas de trafic.

## Modes de défaillance et récupération

Les échecs de planification de capacité se répartissent généralement dans ces catégories :

### OOMKilled (limite mémoire trop basse)

Lorsqu'un conteneur utilise plus de mémoire que sa limite, le noyau tue le processus avec un code de sortie OOMKilled. Vérifiez l'état du pod :

```bash
kubectl get pods -n <namespace>
```

La sortie montre le nombre de `RESTARTS` en augmentation et le `STATUS` comme `CrashLoopBackOff`. Décrivez le pod :

```bash
kubectl describe pod <nom-du-pod> -n <namespace>
```

Recherchez :

```
Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137
```

Récupération : augmentez la limite mémoire d'au moins 20 à 30 % au-dessus du pic d'utilisation observé. Vérifiez également si l'application a une fuite mémoire ; augmenter simplement les limites peut ne faire que reporter le problème.

### Limitation CPU (CPU throttling)

Si l'utilisation du CPU atteint la limite, le noyau limite le conteneur, ce qui augmente la latence sans terminaison. Vérifiez les métriques du conteneur :

```bash
kubectl top pods -n <namespace>
```

Si l'utilisation du CPU est égale ou proche de la limite, inspectez la limitation avec `kubectl describe` sous `Conditions` ou utilisez le metrics-server avec des outils supplémentaires. Récupération : augmentez la limite CPU ou, si la charge est intermittente, envisagez de définir une limite supérieure à la requête pour permettre des bursts.

### Expulsion due à la pression sur le nœud

Si un nœud manque de mémoire, le kubelet expulse les pods selon leur requête/limite et leur priorité. Les pods expulsés montrent le statut `Failed` avec la raison `Evicted`. La récupération peut nécessiter une replanification ou l'ajout de capacité. Vérifiez l'état du nœud :

```bash
kubectl describe node <nom-du-nœud>
```

Recherchez la condition `MemoryPressure` définie sur `True`. Envisagez ensuite de réduire les requêtes mémoire, de déplacer les pods vers d'autres nœuds ou de faire évoluer le cluster.

### Échec de planification

De nouveaux pods peuvent ne pas être planifiés si les requêtes dépassent les ressources disponibles des nœuds. Les événements montrent `FailedScheduling` avec `insufficient cpu` ou `insufficient memory`. Récupération : réduisez les requêtes si elles ont été surestimées, ou ajoutez des nœuds / activez l'autoscaling du cluster.

## Liste de contrôle des opérations

Utilisez cette liste de contrôle pour effectuer les changements de planification de capacité en toute sécurité. Pour chaque élément, nous nommons un responsable et une fréquence de révision.

| # | Vérification | Commande / Action | Résultat attendu | Responsable | Fréquence de révision |
|---|--------------|-------------------|------------------|-------------|----------------------|
| 1 | Confirmer le contexte et l'espace de noms | `kubectl config current-context` et `kubectl get ns` | Cluster et espace de noms corrects | Ingénieur plateforme | À chaque changement |
| 2 | Utilisation de référence | `kubectl top pods -n <namespace>` | Utilisation CPU/mémoire par pod | Responsable DevOps | Hebdomadaire |
| 3 | Identifier les pods sans requêtes/limites | `kubectl get pods -o json \| jq '.items[] | select(.spec.containers[].resources.requests == null) \| .metadata.name'` | Liste des pods non conformes | SRE | Mensuel |
| 4 | Définir requêtes/limites dans les manifestes | Modifier YAML et appliquer | Les pods fonctionnent avec des ressources définies | Propriétaire de l'application | À chaque version |
| 5 | Vérifier le déploiement | `kubectl rollout status deployment/<nom> -n <namespace>` | `successfully rolled out` | Responsable des déploiements | À chaque déploiement |
| 6 | Vérifier l'utilisation réelle par rapport aux requêtes | `kubectl top pods` vs requêtes configurées | Utilisation raisonnable | Responsable DevOps | Hebdomadaire |
| 7 | Tester la récupération après échec | Réduction et augmentation intentionnelles | Les pods se replanifient avec succès | Ingénieur plateforme | Trimestriel |

## Pièges courants et comment les éviter

### Utiliser des requêtes égales aux limites

Beaucoup d'équipes définissent `requêtes = limites` par simplicité. Cela garantit la qualité de service mais empêche les bursts CPU et peut gaspiller la mémoire allouée puisque les requêtes mémoire sont comptées dans la capacité du nœud même si elles ne sont pas utilisées. Pour la mémoire, le surcommit est autorisé, mais un surcommit excessif risque des expulsions. Pour le CPU, autorisez une limite supérieure à la requête pour permettre des bursts si nécessaire, mais soyez conscient de la limitation.

### Définir des limites sans données historiques

Deviner les besoins en ressources conduit souvent à des OOMKills ou à un gaspillage de capacité. Utilisez des données de surveillance sur au moins deux semaines, couvrant les pics et les heures creuses, avant de définir les valeurs. Des outils comme Prometheus et Grafana peuvent aider à visualiser les tendances.

### Ne pas tenir compte du surcoût de démarrage

De nombreuses applications utilisent plus de ressources au démarrage (par exemple, chargement de caches). Définissez les requêtes en fonction de l'utilisation en régime permanent, mais assurez-vous que les limites peuvent absorber le burst de démarrage, ou utilisez une `startupProbe` pour retarder la disponibilité jusqu'à la fin du burst.

### Ignorer l'impact des réplicas sur la capacité des nœuds

Chaque réplica consomme ses requêtes des ressources du nœud. Augmenter les réplicas sans vérifier la capacité des nœuds peut provoquer des échecs de planification. Utilisez `kubectl describe nodes` pour voir les ressources allouées et les comparer à la capacité.

### S'appuyer uniquement sur la mise à l'échelle horizontale

L'Horizontal Pod Autoscaler (HPA) est utile mais ne fonctionne que si les pods ont des requêtes correctement définies. Le HPA répond également lentement par rapport aux pics de trafic. Combinez le HPA avec des marges de ressources raisonnables et, si nécessaire, le Vertical Pod Autoscaler en mode recommandation.

## Conclusion

Une planification de capacité efficace avec kubectl ne consiste pas à deviner les limites ; elle consiste à observer l'utilisation réelle, à définir des requêtes et limites fondées sur des preuves, à vérifier les changements et à planifier la récupération. Le flux de travail est :

1. Inventorier l'environnement et l'état actuel.
2. Établir une référence avec `kubectl top`.
3. Ajuster les requêtes et limites par petits incréments documentés.
4. Vérifier le déploiement avec `kubectl rollout status` et `kubectl get pods`.
5. Surveiller les OOM kills, la limitation et les expulsions.
6. Revoir régulièrement à mesure que les modèles de trafic changent.

En suivant ces pratiques, vous éviterez les pièges courants, réduirez les coûts cloud et maintiendrez la fiabilité des applications. Commencez petit : choisissez un déploiement, appliquez la liste de contrôle et itérez. Votre futur vous, et votre cluster, vous remercieront.