Introduction
L'évacuation sous pression de nœud est l'un des événements les plus perturbateurs dans un cluster Kubernetes en production. Lorsque la mémoire, le disque ou les inodes d'un nœud deviennent insuffisants, le kubelet commence à terminer des pods pour récupérer des ressources. Sans liste de contrôle opérationnelle claire, les équipes sont souvent désorganisées : elles exécutent des commandes au coup par coup, apportent des modifications risquées ou interprètent à tort les signaux d'évacuation de pods comme des défaillances applicatives.
Cet article fournit une liste de contrôle pour les opérations de production relatives à l'évacuation sous pression de nœud Kubernetes. Il s'adresse aux développeurs, consultants DevOps et équipes techniques de startups qui exploitent des clusters ou soutiennent des charges de travail soumises à des contraintes de ressources. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des valeurs temporaires plutôt que des secrets, vérifier le résultat et documenter la procédure de récupération si l'état attendu n'est pas atteint.
Chaque recommandation de cette liste inclut le composant concerné, la plage de versions prise en charge, les prérequis, une étape d'observation en lecture seule, le plus petit changement justifié et une commande ou un signal de vérification. Nous évitons la théorie et donnons des exemples concrets, des sorties attendues et des signaux d'échec.
Utilisez ce guide dans les cas suivants :
- Vous voyez des pods avec le statut
EvictedouOOMKilleddanskubectl get pods. - Vous recevez des alertes concernant des conditions de nœud telles que
MemoryPressureouDiskPressure. - Vous devez ajuster les seuils d'évacuation ou les requêtes/limites de ressources.
- Vous souhaitez diagnostiquer et récupérer systématiquement après un événement de pression sur un nœud.
Tout au long de cet article, nous faisons référence à des domaines connexes comme Node, Resource Requests and Limits et Kubelet uniquement lorsqu'ils affectent les prérequis, la compatibilité, la sécurité, l'observabilité ou la récupération.
Inventaire des versions et de l'environnement
Avant de toucher à un cluster en production, vous devez savoir exactement avec quoi vous travaillez. L'étape d'inventaire des versions et de l'environnement nomme le composant concerné, la plage de versions prise en charge, les prérequis, une commande d'observation en lecture seule, le plus petit changement justifié et la commande ou le signal qui vérifie le résultat.
Pour l'évacuation sous pression de nœud Kubernetes, les composants clés sont :
- Version du plan de contrôle et des nœuds Kubernetes : le comportement d'évacuation change selon les versions. Par exemple, les options
eviction-softeteviction-hardsont stables depuis la v1.12, mais certaines valeurs par défaut ont changé. Vérifiez toujours aveckubectl version. - Version du kubelet : le kubelet est le composant qui applique réellement l'évacuation. Utilisez
kubectl get nodes -o widepuiskubectl describe node <nom-du-nœud>pour voir la version du kubelet. - Runtime de conteneurs : le runtime (containerd, CRI-O, Docker) influence la façon dont l'utilisation de la mémoire et du disque est rapportée. Vérifiez le runtime du nœud avec
kubectl get node <nom-du-nœud> -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}'. - Système d'exploitation et noyau : certains signaux d'évacuation comme
memory.availabledépendent de la version de cgroup (v1 ou v2). Vérifiez l'OS du nœud aveckubectl get node <nom-du-nœud> -o jsonpath='{.status.nodeInfo.osImage}'.
Prérequis
- Accès au cluster avec des permissions suffisantes (au moins
getetdescribesur les nœuds et les pods). kubectlinstallé localement, correspondant à la version mineure du cluster ou à une version mineure près.- Un namespace ou un cluster de test pour des expériences sécurisées.
- Compréhension des ressources allouables du nœud et des demandes de charge existantes.
Observation en lecture seule
Commencez par des commandes en lecture seule pour capturer l'état actuel et les horodatages :
kubectl get nodes -o wide
kubectl describe node <nom-du-nœud> | grep -A 10 Conditions
kubectl get pods --all-namespaces -o wide | grep Evicted
Recherchez des conditions telles que MemoryPressure=True, DiskPressure=True ou PIDPressure=True. Ce sont les premiers signaux d'une évacuation imminente.
Plus petit changement justifié
Ce n'est qu'après avoir observé l'état que vous devez envisager un changement. Une intervention minimale pourrait être :
- Cordonner le nœud pour empêcher la planification de nouveaux pods :
kubectl cordon <nom-du-nœud>. - Ajouter un pod temporaire avec des requêtes généreuses pour vérifier le comportement de planification (uniquement dans un namespace de test).
- Ajuster les requêtes/limites de ressources d'un seul pod dans un environnement hors production d'abord.
Vérification du résultat
Après tout changement, vérifiez le résultat :
kubectl get node <nom-du-nœud> -o jsonpath='{.status.conditions[?(@.type=="MemoryPressure")].status}'
Si la condition passe de True à False, votre changement a eu l'effet escompté.
Séparez toujours l'observation de l'intervention. Capturez d'abord l'état actuel et les horodatages, protégez les informations d'identification et les données privées, puis ne modifiez qu'un élément délimité uniquement lorsque son rayon d'impact et sa procédure de récupération sont compris.
Chemin de configuration sûr
Les seuils d'évacuation du kubelet constituent la configuration principale pour l'évacuation sous pression de nœud. Le chemin de configuration sûr garantit que vous comprenez les options, leurs valeurs par défaut et comment les modifier sans déstabiliser le nœud.
Composant et plage de versions
- Fichier de configuration du kubelet : généralement
/var/lib/kubelet/config.yamlsur le nœud, ou géré par une ConfigMap si vous utilisezkubeadmaveckubelet-config. - Les options liées à l'évacuation sont
--eviction-hard,--eviction-soft,--eviction-soft-grace-period,--eviction-max-pod-grace-period,--eviction-minimum-reclaim, et--system-reserved/--kube-reserved. - Ces options sont stables dans Kubernetes v1.12+ mais vérifiez la documentation de votre version car certaines valeurs par défaut diffèrent entre les fournisseurs cloud et les installations sur site.
Prérequis
- Accès au nœud (SSH ou pod privilégié) pour afficher/modifier la configuration du kubelet, ou permission de mettre à jour la ConfigMap du kubelet si vous utilisez kubeadm.
- Une sauvegarde de la configuration actuelle du kubelet.
- Compréhension de la capacité mémoire et disque de votre nœud.
Observation en lecture seule
Affichez les seuils d'évacuation effectifs actuels :
kubectl proxy &
curl -s http://localhost:8001/api/v1/nodes/<nom-du-nœud>/proxy/configz | jq '.kubeletconfig.evictionHard'
Cela renvoie un objet JSON similaire à :
{
"memory.available": "100Mi",
"nodefs.available": "10%",
"nodefs.inodesFree": "5%",
"imagefs.available": "15%"
}
Si le point de terminaison configz n'est pas activé, vérifiez les options du kubelet sur le nœud :
ps aux | grep kubelet | grep eviction
Ou inspectez le fichier de configuration :
cat /var/lib/kubelet/config.yaml
Plus petit changement justifié
Supposons que vous souhaitiez augmenter le seuil d'évacuation stricte pour la mémoire de 100Mi à 200Mi afin de réduire les évacuations prématurées. Sur un cluster kubeadm, modifiez la ConfigMap du kubelet dans le namespace kube-system :
kubectl edit cm -n kube-system kubelet-config-1.24
Trouvez la section evictionHard et modifiez :
evictionHard:
memory.available: "200Mi"
Redémarrez ensuite le kubelet sur le nœud (un nœud à la fois) :
sudo systemctl restart kubelet
Vérification du résultat
Après le redémarrage, confirmez que le nouveau seuil est actif :
curl -s http://localhost:8001/api/v1/nodes/<nom-du-nœud>/proxy/configz | jq '.kubeletconfig.evictionHard'
La sortie attendue montre "memory.available": "200Mi".
Gardez toujours le test local minimal. Appliquez un seul manifeste ou changement de configuration, inspectez les ressources générées et vérifiez avec des commandes en lecture seule avant de passer à des changements plus larges. Pour les changements du kubelet, envisagez d'utiliser un nœud canari (un nœud non critique) d'abord.
Notes de sécurité
- Ne définissez jamais des seuils
evictionHardtrop bas ; ils peuvent provoquer des évacuations immédiates de pods. - Si vous utilisez l'évacuation douce, définissez des périodes de grâce suffisamment longues pour que les applications sauvegardent leur état.
- Surveillez l'utilisation de la mémoire du nœud après les changements avec
kubectl top node.
Vérification et diagnostic
La vérification et le diagnostic consistent à confirmer que la pression existe, à identifier la source et à comprendre quels pods sont à risque. Cette section fournit une séquence de commandes en lecture seule et les sorties attendues.
Observation en lecture seule
Commencez par le statut des pods à l'échelle du cluster :
kubectl get pods --all-namespaces -o wide
Recherchez les pods avec le statut Evicted, OOMKilled ou CrashLoopBackOff. La raison est indiquée dans la colonne STATUS ou via kubectl describe.
Pour un pod spécifique :
kubectl describe pod <nom-du-pod> -n <namespace>
Dans la section Events, recherchez des messages tels que :
Warning Evicted ... The node was low on resource: memory.
Ou :
Warning OOMKilled ... Container was OOM-killed.
Vérifiez les conditions du nœud :
kubectl describe node <nom-du-nœud> | grep -A 10 Conditions
Si MemoryPressure est True, le nœud est en train de récupérer activement de la mémoire.
Vérifiez l'utilisation actuelle des ressources :
kubectl top node
kubectl top pod -n <namespace>
Comparez l'utilisation de MEMORY(bytes) à Allocatable de kubectl describe node.
Exemple de diagnostic
Supposons que vous voyiez un pod évacué à plusieurs reprises. Exécutez :
kubectl get events --sort-by=.metadata.creationTimestamp | grep Evicted
La sortie peut montrer :
3m Warning Evicted pod/web-app-7b9f8c6d5-xyz The node had condition: [MemoryPressure].
Cela indique que le nœud était sous pression mémoire, et non que le pod lui-même était défaillant.
Vérification du résultat d'une correction
Si vous ajoutez de la mémoire au nœud ou réduisez la charge, vérifiez que la condition de pression disparaît :
kubectl get node <nom-du-nœud> -o jsonpath='{.status.conditions[?(@.type=="MemoryPressure")].status}'
Si la sortie est False, la pression s'est atténuée.
Pour l'évacuation de pods, vérifiez qu'aucune nouvelle évacuation ne se produit après votre intervention en surveillant les événements pendant 10 minutes :
kubectl get events --watch | grep Evicted
Commandes de diagnostic utiles
kubectl describe pod <nom>pour les détails de planification et d'événements.kubectl logs <nom> --previouspour les boucles de crash afin de distinguer les crashs applicatifs des évacuations.kubectl rollout status deployment/<nom>avant de supposer qu'une version a réussi ; un déploiement peut être bloqué en raison de la pression sur le nœud.
Séparez toujours l'observation de l'intervention. Capturez d'abord l'état actuel et les horodatages, protégez les informations d'identification et les données privées, puis ne modifiez qu'un élément délimité uniquement lorsque son rayon d'impact et sa procédure de récupération sont compris.
Modes de défaillance et récupération
L'évacuation sous pression de nœud peut se manifester par plusieurs modes de défaillance. Les comprendre vous aide à récupérer rapidement et en toute sécurité.
Mode de défaillance 1 : évacuation due à la pression mémoire (OOM)
Signal
- Condition de nœud
MemoryPressure=True. - Pods évacués avec la raison
The node was low on resource: memory. - Pods à l'état
OOMKilled.
Étapes de récupération
- Identifiez les pods qui consomment le plus de mémoire :
kubectl top pods --all-namespaces --sort-by=memory. - Pour chaque pod à forte consommation, vérifiez ses requêtes et limites de mémoire :
kubectl get pod <pod> -n <ns> -o yaml | grep -A 5 resources. - Si un pod n'a pas de limite de mémoire, il peut consommer toute la mémoire du nœud. Ajoutez une limite comme mesure d'atténuation temporaire :
resources:
limits:
memory: "512Mi"
requests:
memory: "256Mi"
- Si le nœud est durablement sous-dimensionné, cordonnez-le et drainez-le pour replanifier les pods :
kubectl drain <nom-du-nœud> --ignore-daemonsets --delete-emptydir-data. - Enquêtez sur la cause racine : fuite de mémoire applicative, mise à l'échelle insuffisante des requêtes ou pic de trafic soudain.
Vérification
Après avoir appliqué les limites, assurez-vous qu'il n'y a plus de tueries OOM :
kubectl get pods --all-namespaces -o wide | grep OOMKilled
Ne devrait renvoyer aucun résultat après un certain temps.
Mode de défaillance 2 : évacuation due à la pression disque
Signal
- Condition de nœud
DiskPressure=True. - Pods évacués avec la raison
The node was low on resource: ephemeral-storageounodefs. - Utilisation du disque du nœud supérieure à 80-90 % pour le système de fichiers utilisé par les journaux de conteneurs ou les images.
Étapes de récupération
- Vérifiez l'utilisation du disque sur le nœud (si accessible) :
df -h /var/lib/containerd /var/log. - Nettoyez les images inutilisées :
crictl rmi --prune(sur le nœud). - Supprimez les anciens journaux de conteneurs :
journalctl --vacuum-size=200Moutruncate -s 0 /var/log/containers/*.log(attention aux journaux actifs). - Si la pression est due aux requêtes de stockage éphémère, définissez
resources.requests.ephemeral-storagesur les pods pour appliquer la planification de capacité. - Si le disque du nœud est plein, drainez et reprovisionnez après nettoyage.
Vérification
Vérifiez la condition :
kubectl get node <nom-du-nœud> -o jsonpath='{.status.conditions[?(@.type=="DiskPressure")].status}'
Devrait renvoyer False.
Mode de défaillance 3 : évacuation due à la pression PID
Signal
- Condition de nœud
PIDPressure=True. - Les pods en cours d'exécution montrent
fork: retry: Resource temporarily unavailabledans les journaux. - Le système peut ne pas répondre en raison de l'épuisement des processus.
Étapes de récupération
- Identifiez le nombre de processus sur le nœud :
ps -eLf | wc -l(si accès au nœud). - Réduisez les limites PID par pod en définissant
resources.requests.pidsoulimits.pidsdans les spécifications de pod. - Redémarrez les processus qui fuient (bug applicatif).
- Augmentez
pid_maxsur le nœud s'il est trop bas :sysctl kernel.pid_max=32768(temporaire).
Vérification
Vérifiez la condition :
kubectl get node <nom-du-nœud> -o jsonpath='{.status.conditions[?(@.type=="PIDPressure")].status}'
Devrait renvoyer False.
Mode de défaillance 4 : évacuation des pods système critiques
Signal
- Des pods
kube-systemtels quekube-dns,kube-proxyou les pods CNI sont évacués. - Les fonctions du cluster se dégradent.
Étapes de récupération
- Assurez-vous que les pods critiques ont des classes de priorité élevées. Vérifiez la priorité :
kubectl get pod -n kube-system -o yaml | grep priorityClassName. - Si ce n'est pas défini, créez une classe de priorité élevée et attribuez-la aux pods critiques.
- Augmentez temporairement les ressources du nœud ou réduisez la charge.
- Enquêtez sur la raison pour laquelle les pods système sont sous pression ; ils ont peut-être des requêtes insuffisantes.
Vérification
Assurez-vous que les pods système sont en cours d'exécution et non évacués après la récupération :
kubectl get pods -n kube-system | grep -v Running
Ne devrait montrer que des pods terminés ou aucun.
Pour tous les modes de défaillance, documentez toujours la procédure de récupération et les sorties attendues pour les incidents futurs.
Liste de contrôle des opérations
Cette section consolide l'ensemble du flux de travail en une liste de contrôle concise et actionnable pour les opérations en production. Utilisez-la avant, pendant et après un événement de pression sur un nœud.
Liste de contrôle avant incident
- [ ] Vérifiez la version du cluster et du kubelet :
kubectl versionetkubectl get nodes -o wide. - [ ] Examinez les seuils d'évacuation actuels :
curl -s http://localhost:8001/api/v1/nodes/<nœud>/proxy/configz | jq '.kubeletconfig.evictionHard'. - [ ] Confirmez la surveillance des conditions de nœud : configurez des alertes pour
MemoryPressure,DiskPressure,PIDPressuredurant plus de 5 minutes. - [ ] Assurez-vous que tous les pods de production ont des requêtes et limites de ressources pour le CPU, la mémoire et le stockage éphémère.
- [ ] Vérifiez que les pods critiques de haute priorité ont des PriorityClasses.
- [ ] Documentez une base de référence de l'utilisation normale des ressources du nœud avec
kubectl top node. - [ ] Pratiquez une récupération simulée : simulez une pression mémoire en déployant un pod gourmand en mémoire dans un namespace de test et suivez la liste de contrôle.
Exemple d'exercice de simulation
Dans un namespace de test, déployez :
apiVersion: v1
kind: Pod
metadata:
name: memory-hog
spec:
containers:
- name: stress
image: polinux/stress
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "500M", "--vm-hang", "1"]
Surveillez avec kubectl top pod memory-hog et observez la pression mémoire du nœud. Ensuite, tuez le pod et vérifiez la récupération.
Liste de contrôle pendant l'incident
- [ ] Identifiez le nœud affecté :
kubectl get nodes -o wideet recherchez les conditions de pression. - [ ] Déterminez le type de pression : mémoire, disque ou PID.
- [ ] Pour la mémoire : listez les pods les plus consommateurs :
kubectl top pods --all-namespaces --sort-by=memory. - [ ] Pour le disque : vérifiez le système de fichiers du nœud et nettoyez les images/journaux si cela est sûr.
- [ ] Cordonnez le nœud si vous devez empêcher la planification :
kubectl cordon <nœud>. - [ ] Drainez le nœud si vous devez déplacer les charges de travail :
kubectl drain <nœud> --ignore-daemonsets --delete-emptydir-data. - [ ] Ne supprimez pas manuellement les pods sauf si nécessaire ; l'évacuation est le travail du kubelet, et la suppression manuelle peut provoquer des oscillations.
- [ ] Communiquez le statut aux parties prenantes avec des horodatages.
Liste de contrôle après incident
- [ ] Vérifiez que les conditions de pression sont levées :
kubectl get node <nœud> -o jsonpath='{.status.conditions[?(@.type=="MemoryPressure")].status}'. - [ ] Vérifiez que tous les pods évacués ont été replanifiés et sont en cours d'exécution :
kubectl get pods --all-namespaces | grep -v Running. - [ ] Examinez les journaux et événements pour trouver la cause racine :
kubectl get events --sort-by=.metadata.creationTimestamp | grep -E 'Evicted|OOM'. - [ ] Ajustez les requêtes/limites de ressources ou les seuils d'évacuation en fonction des conclusions.
- [ ] Mettez à jour la documentation et les procédures opérationnelles.
- [ ] Planifiez une réunion post-mortem et assignez des actions (par exemple, « Priya Shah, responsable ingénierie : augmenter la mémoire des nœuds de 25 % sous 2 semaines »).
Vérifications Kubernetes pratiques
Commencez par kubectl get pods -o wide, puis utilisez kubectl describe pod <nom> pour les détails de planification et d'événements, kubectl logs <nom> --previous pour les boucles de crash, et kubectl rollout status deployment/<nom> avant de supposer qu'une version a réussi.
Gardez le test local minimal. Appliquez un seul manifeste, inspectez les ressources générées et vérifiez le trafic avec kubectl port-forward ou un type de service local avant de passer à un équilibreur de charge cloud ou à un contrôleur d'entrée.
Conclusion
La liste de contrôle des opérations de production pour l'évacuation sous pression de nœud Kubernetes avec des exemples pratiques n'est utile que si chaque recommandation est limitée à une version, observable et réversible lorsque la technologie le permet. Copier une commande sans vérifier les prérequis et la sortie attendue n'est pas une procédure opérationnelle.
Cet article a fourni une liste de contrôle complète couvrant l'inventaire des versions, la configuration sûre, le diagnostic, les modes de défaillance et la récupération. Nous avons insisté sur l'observation en lecture seule d'abord, les changements minimaux et la vérification après chaque étape.
Comme prochaine étape, choisissez une vérification à faible risque pour l'évacuation sous pression de nœud Kubernetes en production, enregistrez l'état actuel, exécutez la vérification documentée, comparez le résultat avec le signal attendu et examinez les dépendances telles que Node, Resource Requests and Limits et Kubelet.
Un flux de travail technique 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.
Utilisez cette liste de contrôle comme un document vivant : après chaque incident, mettez-la à jour avec de nouvelles observations et leçons apprises. Cette amélioration itérative rendra vos opérations Kubernetes plus résilientes au fil du temps.