## Introduction Les erreurs de configuration des nœuds figurent parmi les causes les plus fréquentes d'instabilité des clusters Kubernetes, mais elles passent souvent inaperçues jusqu'à ce que les charges de travail commencent à échouer. Un kubelet mal configuré, une étiquette manquante ou une teinte incorrecte peuvent perturber silencieusement l'ordonnancement, casser la mise en réseau ou faire basculer les nœuds entre les états Ready et NotReady, laissant les équipes se démener pour diagnostiquer la cause racine. Ce guide s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui gèrent des clusters Kubernetes et souhaitent passer de la réaction aux incidents à la prévention. Il se concentre sur des techniques pratiques et éprouvées sur le terrain pour configurer correctement les nœuds, détecter rapidement les erreurs et récupérer en toute sécurité lorsque les choses tournent mal. Vous y trouverez des commandes concrètes, les résultats attendus, les signaux de défaillance et les décisions de récupération correspondant à des scénarios réels. Le principe sous-jacent est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés plutôt que des secrets, vérifier chaque résultat et toujours savoir comment effectuer un retour en arrière. Au lieu de traiter la configuration comme une tâche ponctuelle, ce guide l'envisage comme un cycle continu de validation et d'amélioration. ## Inventaire des versions et de l'environnement Avant de toucher à la configuration d'un nœud, vous devez avoir une vision claire de votre environnement. Commencez par identifier la version de Kubernetes, le système d'exploitation du nœud, le moteur d'exécution de conteneurs et le plugin réseau. Ces détails déterminent les options de configuration disponibles et les problèmes connus que vous pourriez rencontrer. Sur n'importe quel nœud, exécutez ces commandes en lecture seule pour capturer l'état actuel : ```bash kubectl get nodes -o wide kubectl version --short cat /etc/os-release ``` La sortie attendue de `kubectl get nodes -o wide` comprend les colonnes NAME, STATUS, ROLES, AGE, VERSION, INTERNAL-IP, EXTERNAL-IP, OS-IMAGE, KERNEL-VERSION et CONTAINER-RUNTIME. Par exemple : ``` NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node-1 Ready 12d v1.27.3 10.0.0.5 Ubuntu 22.04.2 LTS 5.15.0-76-generic containerd://1.7.2 ``` Enregistrez toujours l'état actuel avant d'effectuer des modifications. Sauvegardez la sortie dans un fichier horodaté, par exemple `node-state-2025-03-01.txt`. Cette base de référence est précieuse pour le retour en arrière et le dépannage. Lorsque vous effectuez une modification, ne modifiez qu'un seul élément à la fois. Par exemple, si vous devez mettre à jour à la fois la configuration du kubelet et les étiquettes du nœud, faites d'abord le kubelet, vérifiez qu'il fonctionne, puis mettez à jour les étiquettes. Cela réduit le risque d'introduire plusieurs variables qui compliquent le débogage. ## Chemin de configuration sûr Les modifications de configuration des nœuds doivent suivre un chemin discipliné : planifier, appliquer sur un nœud canari, vérifier, puis déployer. Ne modifiez jamais les fichiers de configuration directement sur un nœud de production sans avoir testé sur un nœud non critique au préalable. Un scénario courant consiste à ajouter une étiquette personnalisée à un nœud à des fins d'ordonnancement. Au lieu d'exécuter aveuglément `kubectl label node node-1 tier=frontend`, vérifiez d'abord les étiquettes existantes : ```bash kubectl get node node-1 --show-labels ``` La sortie attendue peut inclure des étiquettes comme `kubernetes.io/hostname=node-1`, `node-role.kubernetes.io/worker=` et toutes les étiquettes personnalisées déjà appliquées. Après avoir confirmé que l'étiquette n'entre pas en conflit avec celles existantes, appliquez-la : ```bash kubectl label node node-1 tier=frontend ``` Vérifiez que l'étiquette est présente : ```bash kubectl get node node-1 --show-labels | grep tier=frontend ``` Si l'étiquette est incorrecte, supprimez-la avec `kubectl label node node-1 tier-` (notez le tiret final). Pour la configuration du kubelet, utilisez un fichier de configuration versionné plutôt que des indicateurs en ligne de commande. Par exemple, créez `/var/lib/kubelet/config.yaml` avec : ```yaml apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration maxPods: 110 systemReserved: cpu: 500m memory: 1Gi kubeReserved: cpu: 250m memory: 512Mi ``` Ensuite, redémarrez le kubelet et vérifiez son état : ```bash systemctl restart kubelet systemctl status kubelet journalctl -u kubelet -n 50 ``` L'état doit indiquer `active (running)` et les journaux ne doivent contenir aucun message d'erreur. Pour confirmer que les paramètres ont pris effet, inspectez les ressources allouables du nœud : ```bash kubectl describe node node-1 | grep -A5 "Allocatable" ``` La sortie doit refléter la réduction du CPU et de la mémoire due aux réservations. ## Vérification et diagnostic Après avoir effectué une modification de configuration, une vérification systématique est essentielle. Utilisez une combinaison de commandes en lecture seule, d'inspection des journaux et de tests ciblés pour confirmer que le nœud se comporte comme prévu. Commencez par l'état général du nœud : ```bash kubectl get node node-1 kubectl describe node node-1 ``` Un nœud sain est `Ready` sans conditions de pression comme `MemoryPressure`, `DiskPressure` ou `PIDPressure`. Si une condition est `True`, enquêtez immédiatement. Pour diagnostiquer un nœud `NotReady`, vérifiez d'abord le service kubelet : ```bash systemctl status kubelet journalctl -u kubelet --since "10 minutes ago" ``` Les erreurs courantes incluent l'expiration du certificat, les défaillances du plugin réseau ou les problèmes d'espace disque. Par exemple, une ligne de journal comme `failed to get cgroup stats for /system.slice/kubelet.service` suggère une incompatibilité de pilote cgroup. Pour les problèmes au niveau des pods sur un nœud, utilisez : ```bash kubectl get pods -o wide --field-selector spec.nodeName=node-1 kubectl describe pod kubectl logs --previous ``` La sortie de `describe` montre les événements, tels que les échecs d'ordonnancement dus à des teintes ou à des ressources insuffisantes. Pour un pod bloqué dans `CrashLoopBackOff`, les journaux `--previous` révèlent souvent la cause racine. Si vous devez tester la connectivité vers un service sur le nœud, utilisez `kubectl port-forward` : ```bash kubectl port-forward svc/my-service 8080:80 ``` Ensuite, accédez à `localhost:8080` depuis votre machine locale. Cela vérifie que le service et le pod fonctionnent sans les exposer extérieurement. ## Modes de défaillance et récupération Les erreurs arrivent. La clé est de reconnaître rapidement les modes de défaillance et d'avoir un plan pour récupérer avec un minimum de perturbations. Une erreur fréquente consiste à appliquer involontairement une teinte à un nœud, provoquant l'éviction de tous les pods. Par exemple, exécuter `kubectl taint node node-1 dedicated=special-user:NoSchedule` sans comprendre l'effet peut perturber les charges de travail. Pour éviter cela, effectuez toujours un essai à blanc d'abord : ```bash kubectl taint node node-1 dedicated=special-user:NoSchedule --dry-run=client ``` La sortie montre ce qui se passerait sans appliquer réellement la teinte. Si vous l'avez appliquée par erreur, supprimez-la avec : ```bash kubectl taint node node-1 dedicated=special-user:NoSchedule- ``` La récupération d'un kubelet mal configuré implique souvent un retour à une configuration précédente. Stockez les fichiers de configuration dans un système de contrôle de version et sauvegardez-les avant de les modifier. Par exemple, avant de modifier `/var/lib/kubelet/config.yaml`, copiez-le : ```bash cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak-2025-03-01 ``` Si le nœud échoue après le redémarrage, restaurez la sauvegarde et redémarrez le kubelet : ```bash cp /var/lib/kubelet/config.yaml.bak-2025-03-01 /var/lib/kubelet/config.yaml systemctl restart kubelet ``` Une autre défaillance courante est le manque d'espace disque dû aux journaux des conteneurs. Surveillez l'utilisation du disque du nœud avec `df -h` et configurez la rotation des journaux. Pour containerd, définissez `max_container_log_line_size` et `max_concurrent_downloads` dans la configuration, mais pour la rotation des journaux, utilisez le paramètre `ContainerLogMaxSize` dans la configuration du kubelet ou configurez le pilote de journalisation du moteur d'exécution. ## Liste de contrôle des opérations Utilisez cette liste de contrôle avant et après toute modification de configuration de nœud pour vous assurer que rien n'est oublié. **Avant la modification :** - [ ] Enregistrer l'état actuel du nœud : `kubectl get nodes -o wide > nodes-before.txt` - [ ] Vérifier les conditions du nœud : `kubectl describe node node-1 | grep -A5 Conditions` - [ ] Sauvegarder les fichiers de configuration : `cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak` - [ ] Identifier la procédure de retour en arrière pour la modification spécifique. - [ ] Informer les membres de l'équipe concernés (par exemple, via le canal Slack #k8s-ops). - [ ] Évaluer l'impact : combien de pods et de services dépendent de ce nœud ? **Après la modification :** - [ ] Vérifier que le nœud est Ready : `kubectl get node node-1` - [ ] Rechercher de nouvelles erreurs dans les journaux du kubelet : `journalctl -u kubelet --since "5 minutes ago" | grep -i error` - [ ] Confirmer que les pods clés fonctionnent : `kubectl get pods -o wide --field-selector spec.nodeName=node-1` - [ ] Tester l'ordonnancement d'un pod simple : `kubectl run test-pod --image=busybox --restart=Never -- sleep 10` puis vérifier son état. - [ ] Réexécuter la commande de référence et comparer avec l'état antérieur. - [ ] Documenter la modification et le résultat dans le runbook de l'équipe. Pour chaque élément de la liste, attribuez un responsable unique. Par exemple, l'ingénieur de plateforme de garde est responsable des vérifications avant modification, tandis que le responsable DevOps est responsable de la vérification après modification. Révisez la liste de contrôle trimestriellement pour intégrer les leçons apprises. ## Pièges courants Plusieurs erreurs récurrentes peuvent saboter les efforts de configuration des nœuds. Voici les plus fréquentes et comment les éviter. **1. Ignorer les réservations de ressources** De nombreux opérateurs ne définissent pas `systemReserved` et `kubeReserved` dans la configuration du kubelet. Sans ces réservations, le nœud peut surallouer les ressources, ce qui entraîne une concurrence entre les processus système et les pods et provoque une instabilité. Réservez toujours du CPU et de la mémoire pour le système d'exploitation et les démons Kubernetes. Exemple de configuration : ```yaml systemReserved: cpu: 500m memory: 1Gi kubeReserved: cpu: 250m memory: 512Mi ``` Vérifiez la capacité allouable du nœud après application : `kubectl describe node node-1 | grep Allocatable` doit montrer des ressources réduites. **2. Pilotes cgroup incompatibles entre le moteur d'exécution et le kubelet** Si le kubelet utilise le pilote cgroup `systemd` mais que le moteur d'exécution de conteneurs utilise `cgroupfs`, vous pouvez voir des avertissements et un comportement imprévisible. Assurez-vous que les deux utilisent le même pilote. Pour containerd, vérifiez `/etc/containerd/config.toml` pour `SystemdCgroup = true`. Pour le kubelet, vérifiez `cgroupDriver: systemd` dans la configuration. **3. Oublier de drainer un nœud avant la maintenance** Effectuer une maintenance sans drainer entraîne des évictions de pods inattendues et des interruptions de service. Utilisez `kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data` pour évacuer gracieusement les pods avant de travailler sur le nœud. Après la maintenance, décordez avec `kubectl uncordon node-1`. **4. Appliquer des modifications sans essai à blanc** Les erreurs comme des teintes ou des étiquettes incorrectes peuvent être évitées avec `--dry-run=client`. Cet indicateur montre ce qui se passerait sans apporter de modifications. Par exemple, `kubectl taint node node-1 key=value:NoSchedule --dry-run=client` révèle l'effet sans l'appliquer. **5. Ne pas surveiller en continu la santé des nœuds** Les problèmes de nœuds se développent souvent avec le temps. Configurez des alertes pour les conditions des nœuds, l'utilisation du disque et les redémarrages du kubelet. Des outils comme Prometheus et Node Exporter peuvent collecter des métriques, et Alertmanager peut vous notifier lorsque les seuils sont dépassés. Par exemple, alertez lorsque l'utilisation du disque du nœud dépasse 80 %. ## Conclusion La configuration des nœuds Kubernetes est un aspect critique de la gestion de cluster qui exige une attention minutieuse et une vérification systématique. Les erreurs décrites dans ce guide, des réservations de ressources manquantes à l'omission des essais à blanc, sont évitables avec les bonnes pratiques. Commencez par inventorier votre environnement et comprendre l'état actuel. Apportez des modifications de manière incrémentale, en vérifiant toujours après chaque étape. Utilisez des essais à blanc pour prévenir les erreurs et ayez un plan de retour en arrière prêt. Attribuez des responsabilités claires et révisez régulièrement vos processus pour les maintenir efficaces. Comme prochaine étape, choisissez une vérification à faible risque de ce guide, comme vérifier les conditions du nœud ou tester une teinte avec essai à blanc. Enregistrez l'état actuel, exécutez la vérification, comparez le résultat avec la sortie attendue et documentez vos conclusions. Au fil du temps, ces petites étapes construisent une culture opérationnelle solide qui maintient vos clusters stables et vos charges de travail en cours d'exécution. Une configuration fiable des nœuds ne consiste pas seulement à éviter les erreurs ; il s'agit de renforcer la confiance dans votre infrastructure. En suivant les conseils pratiques de ce guide, vous pouvez prévenir les incidents avant qu'ils ne surviennent et récupérer rapidement lorsqu'ils se produisent.