Introduction
Kubelet est l’agent de nœud Kubernetes qui s’assure que les conteneurs s’exécutent dans les pods conformément à leurs spécifications. Si son utilisation de base est simple, les concepts avancés comme la gestion de la configuration, le traitement des ressources et le dépannage exigent une compréhension plus fine pour fonctionner de manière fiable à grande échelle. Cet article explique les rouages, l’architecture et la configuration de Kubelet avec des exemples pratiques, en mettant l’accent sur les commandes actionnables, les sorties attendues et les stratégies de récupération.
Nous ciblons les développeurs, les consultants DevOps et les équipes techniques de startups qui doivent diagnostiquer les problèmes de nœuds, optimiser l’utilisation des ressources ou sécuriser la configuration de Kubelet. Chaque exemple inclut des commandes adaptées à la version, les prérequis et les étapes de validation. Vous apprendrez à observer avant de modifier, à limiter le rayon d’impact et à documenter les chemins de récupération, des pratiques essentielles dans les environnements Kubernetes de production.
Inventaire des versions et de l’environnement
Avant toute tâche avancée sur Kubelet, établissez une base de référence claire. Cela signifie connaître la version de Kubelet, son mode de déploiement et les fichiers de configuration utilisés. Un tel inventaire permet d’éviter des modifications inappropriées et facilite la récupération.
Identifier la version et le déploiement de Kubelet
Exécutez la commande en lecture seule suivante sur le nœud pour obtenir la version de Kubelet :
kubelet --version
Sortie attendue :
Kubernetes v1.28.2
La méthode de déploiement est importante. Vérifiez si Kubelet s’exécute comme un service systemd (courant dans les clusters kubeadm) ou comme un binaire statique géré par un autre processus. Sur un nœud basé sur systemd, utilisez :
systemctl status kubelet
Observez la ligne Loaded: ; elle indique le chemin du fichier d’unité, par exemple /etc/systemd/system/kubelet.service. Si Kubelet est conteneurisé (par exemple, dans certaines distributions gérées), vous devrez peut-être utiliser docker ps ou crictl ps pour le localiser.
Inventorier les fichiers de configuration
Kubelet lit la configuration à partir de plusieurs sources, avec un ordre de priorité. Les emplacements courants incluent :
- Les paramètres passés au binaire kubelet (priorité la plus élevée pour de nombreuses options)
- Le fichier
--config, généralement/var/lib/kubelet/config.yaml - Les fichiers drop-in dans
/etc/systemd/system/kubelet.service.d/ou/etc/default/kubelet - Les valeurs par défaut
Pour voir la configuration active, exécutez :
kubelet --config /var/lib/kubelet/config.yaml --dump-config
Cela affiche la configuration effective au format JSON/YAML. Comparez-la avec le fichier pour identifier les surcharges provenant des paramètres.
Capturer l’état actuel
Prenez un instantané de l’état du nœud et des métriques Kubelet pertinentes avant toute modification. Utilisez :
kubectl describe node <node-name>
Remplacez <node-name> par le nom réel du nœud. Notez les conditions telles que MemoryPressure, DiskPressure et PIDPressure. Enregistrez également les horodatages pour la corrélation.
Pour les métriques Kubelet en direct, si le point de terminaison des métriques Kubelet est activé (par défaut sur le port 10250), vous pouvez l’interroger avec une authentification appropriée, mais pour simplifier, de nombreux clusters exposent les métriques via l’exportateur de nœuds Prometheus. Vérifiez si le port 10255 (lecture seule) est disponible :
curl -s http://localhost:10255/metrics | head
Remarque : le port en lecture seule est désactivé par défaut dans les versions récentes de Kubernetes pour des raisons de sécurité. Préférez utiliser kubectl proxy et curl depuis un plan de contrôle avec les autorisations appropriées.
Stockez ces sorties dans un emplacement sécurisé. N’incluez jamais de secrets ni de clés privées dans votre documentation.
Définir les signaux attendus et d’échec
Pour tout changement, définissez à quoi ressemble le succès. Par exemple, si vous prévoyez d’ajuster les seuils evictionHard, le résultat attendu pourrait être : « La condition de nœud MemoryPressure reste False sous un stress mémoire allant jusqu’à 80 % d’utilisation. » Un signal d’échec pourrait être : « Les journaux de Kubelet montrent Failed to admit pod ou des avertissements EvictionThresholdMet. » Documentez ces éléments avant d’intervenir.
Chemin de configuration sûr
Modifier la configuration de Kubelet peut déstabiliser un nœud. Suivez un processus structuré pour minimiser les risques.
Prérequis pour les modifications de configuration
- Accès au nœud avec les privilèges sudo.
- Capacité de redémarrer le service Kubelet (peut causer une brève interruption des pods ; prévoyez une fenêtre de maintenance).
- Une sauvegarde du fichier de configuration actuel.
- Compréhension du rôle du nœud : plan de contrôle ou worker.
Exemple : ajuster les seuils d’éviction des pods
Kubelet évince les pods lorsque les ressources du nœud sont épuisées. Les valeurs par défaut peuvent être trop agressives pour certaines charges de travail. Ajustons le seuil d’éviction stricte pour la mémoire.
Étape 1 : Observer les réglages actuels.
grep -A5 evictionHard /var/lib/kubelet/config.yaml
La sortie peut montrer :
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
imagefs.available: "15%"
Étape 2 : Déterminer la valeur souhaitée.
Pour un nœud avec 32 Gio de RAM exécutant des applications sensibles à la mémoire, vous pourriez augmenter memory.available à 500Mi pour réserver plus de marge. Cela réduit le risque de terminaisons OOM au prix d’une mémoire allouable plus faible.
Étape 3 : Effectuer une modification ciblée.
Modifiez le fichier de configuration à l’aide d’un éditeur de texte :
sudo vi /var/lib/kubelet/config.yaml
Modifiez uniquement la ligne concernant la mémoire :
evictionHard:
memory.available: "500Mi"
Enregistrez et quittez.
Étape 4 : Valider la syntaxe de la configuration.
Kubelet peut valider sa configuration sans démarrer :
kubelet --config /var/lib/kubelet/config.yaml --validate
Aucune sortie ne signifie que la syntaxe est valide. En cas d’erreurs, corrigez-les.
Étape 5 : Redémarrer Kubelet.
sudo systemctl restart kubelet
Étape 6 : Vérifier que le changement a pris effet.
Vérifiez la configuration effective de Kubelet :
kubelet --config /var/lib/kubelet/config.yaml --dump-config | grep memory.available
La sortie attendue inclut "memory.available": "500Mi".
Surveillez également les conditions du nœud :
kubectl get node <node-name> -o jsonpath='{range .status.conditions[*]}{.type}={.status}{"\n"}{end}'
Recherchez la condition MemoryPressure avec le statut False et des événements indiquant aucune nouvelle éviction.
Chemin de récupération
Si les pods commencent à être évincés de manière inattendue ou si le nœud devient instable, revenez à la sauvegarde :
sudo cp /var/lib/kubelet/config.yaml.bak /var/lib/kubelet/config.yaml
sudo systemctl restart kubelet
Vérifiez avec --dump-config et l’état du nœud. C’est pourquoi les sauvegardes sont essentielles.
Considérations sur le rayon d’impact
Une modification sur un seul nœud n’affecte que les pods de ce nœud, sauf s’il s’agit d’un modèle de configuration partagé (par exemple, dans les scripts d’approvisionnement du cluster). Si vous utilisez un système de gestion de configuration (Ansible, Terraform), modifiez la source de vérité et déployez progressivement avec un cordon/drain du nœud pour éviter des perturbations massives des pods.
Vérification et diagnostics
Après tout changement, la vérification est essentielle. Au-delà de l’exemple ci-dessus, voici des diagnostics avancés pour Kubelet.
Inspecter les journaux de Kubelet
Comme Kubelet s’exécute en tant que service, utilisez journalctl :
sudo journalctl -u kubelet -n 100 --no-pager
Pour suivre en direct :
sudo journalctl -u kubelet -f
Recherchez des motifs : lignes E (erreur) répétées, avertissements concernant des échecs de synchronisation, etc. Corrélez avec les événements du nœud :
kubectl get events --field-selector involvedObject.kind=Node
Si les journaux sont trop bruyants, augmentez temporairement la verbosité de Kubelet en modifiant l’unité systemd :
sudo systemctl edit kubelet
Ajoutez :
[Service]
Environment="KUBELET_EXTRA_ARGS=--v=4"
Puis redémarrez et observez. N’oubliez pas de supprimer ceci après le débogage ; une verbosité élevée nuit aux performances.
Interroger l’API Kubelet pour les spécifications des pods
Kubelet expose une API en lecture seule (si activée) pour voir ce qu’il pense exécuter. Le point de terminaison pods peut être utile. Depuis le nœud :
curl -s http://localhost:10255/pods
Cependant, le port en lecture seule (10255) est obsolète et souvent désactivé. Le port sécurisé (10250) nécessite des certificats clients. Vous pouvez utiliser kubectl proxy et curl depuis un plan de contrôle ou une machine locale :
# Démarrez le proxy dans un terminal séparé
kubectl proxy --port=8001
# Puis interrogez le point de terminaison des pods
curl -X GET http://127.0.0.1:8001/api/v1/nodes/<node-name>/proxy/pods | jq .
Cela renvoie la liste des pods connus de Kubelet. Comparez avec kubectl get pods --all-namespaces pour repérer les divergences (par exemple, des conteneurs orphelins).
Vérification des pods statiques
Si vous utilisez des pods statiques (par exemple, pour les composants du plan de contrôle), vérifiez le répertoire des manifestes de pods statiques (par défaut /etc/kubernetes/manifests). Kubelet surveille ce répertoire et crée des pods. Pour vérifier qu’un pod statique est reconnu, recherchez dans les journaux de Kubelet des lignes telles que :
"Starting pod" pod="kube-system/kube-apiserver-<node>"
Ou interrogez le point de terminaison spec de l’API Kubelet pour les pods statiques.
Analyse approfondie des métriques
Kubelet expose des métriques via le port sécurisé, généralement collectées par Prometheus. Accédez-y via kubectl proxy :
# Démarrez le proxy s’il n’est pas déjà en cours d’exécution
kubectl proxy --port=8001
# Interrogez les métriques
curl -sSL http://127.0.0.1:8001/api/v1/nodes/<node-name>/proxy/metrics | grep kubelet_runtime_operations
Métriques clés :
kubelet_runtime_operations_total: nombre d’opérations d’exécution de conteneurs par type.kubelet_runtime_operations_errors_total: erreurs dans les opérations d’exécution.kubelet_pod_start_duration_seconds: temps de démarrage des pods.
Des taux d’erreur élevés ou des durées longues peuvent indiquer des problèmes d’exécution. Utilisez-les pour les alertes.
Modes de défaillance et récupération
Kubelet peut échouer de diverses manières. Comprendre les modes de défaillance courants accélère la récupération.
Nœud non prêt
Symptôme : kubectl get nodes affiche NotReady pour le nœud.
Diagnostic :
kubectl get node <node-name> -o jsonpath='{range .status.conditions[*]}{.type}={.status}{"\n"}{end}'
Regardez la condition Ready : False avec une raison comme KubeletNotReady ou ContainerRuntimeUnhealthy.
Vérifiez les journaux de Kubelet pour les erreurs. Vérifiez également si le runtime de conteneurs fonctionne :
sudo systemctl status containerd # ou docker
Si le runtime est arrêté, redémarrez-le :
sudo systemctl restart containerd
sudo systemctl restart kubelet
Récupération : Après le redémarrage, attendez 1 à 2 minutes et vérifiez l’état du nœud. S’il est toujours NotReady, inspectez les journaux pour des problèmes de certificat ou de réseau (par exemple, impossibilité de contacter le serveur API).
Échec de rotation des certificats Kubelet
Kubelet utilise des certificats clients pour s’authentifier auprès du serveur API. Ces certificats sont renouvelés automatiquement, mais une défaillance peut entraîner des problèmes d’accès à l’API.
Symptôme : Les journaux de Kubelet affichent Failed to rotate client certificate ou Unauthorized.
Diagnostic : Vérifiez l’expiration du certificat :
sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
S’il est expiré et non renouvelé, vérifiez le paramètre --rotate-certificates et l’approbateur kubelet-serving-cert-approver (le cas échéant).
Récupération : Approuvez manuellement les CSR en attente :
kubectl get csr | grep Pending
kubectl certificate approve <csr-name>
S’il n’y a pas de CSR, redémarrez Kubelet pour déclencher une nouvelle demande. Pour prévenir ce problème, assurez-vous que le gestionnaire de contrôleurs dispose des paramètres --cluster-signing-cert-file et --cluster-signing-key-file.
Pression disque et évictions
Lorsque l’espace disque du nœud est faible, Kubelet peut évincer des pods. Si la configuration est incorrecte, cela peut entraîner un effet de battement.
Symptôme : Évictions fréquentes de pods avec la condition DiskPressure à True.
Diagnostic : Vérifiez l’utilisation du disque et les seuils d’éviction de Kubelet.
df -h /var/lib/kubelet
Examinez la configuration evictionHard et evictionSoft.
Récupération : Libérez temporairement de l’espace (supprimez les images inutilisées, les journaux) et ajustez les seuils. Pour supprimer les images inutilisées, utilisez crictl rmi --prune si vous utilisez containerd. Modifiez ensuite les seuils comme dans la section précédente.
Pièges courants et comment les éviter
- Mauvaise compréhension de la priorité de configuration
Pourquoi cela arrive : Les paramètres de Kubelet remplacent les réglages du fichier de configuration, et les utilisateurs peuvent définir une valeur aux deux endroits sans le savoir. Comment l’éviter : Utilisez toujours --dump-config pour voir la configuration effective. Documentez tous les changements de paramètres et de fichiers dans votre automatisation.
- Ignorer les conditions du nœud
Pourquoi cela arrive : Les opérateurs se concentrent sur l’état des pods mais négligent les pressions au niveau du nœud. Comment l’éviter : Configurez des alertes de surveillance pour MemoryPressure, DiskPressure et PIDPressure. Utilisez régulièrement kubectl describe node.
- Seuils d’éviction trop agressifs
Pourquoi cela arrive : Réglage pour une utilisation maximale des ressources sans tenir compte des pics de charge. Comment l’éviter : Définissez des seuils conservateurs (par exemple, memory.available: 500Mi pour les nœuds à mémoire élevée), testez avec une charge et surveillez les événements d’éviction.
- Redémarrer Kubelet sans drainer
Pourquoi cela arrive : Oublier que le redémarrage interrompt tous les pods du nœud, provoquant une indisponibilité temporaire. Comment l’éviter : Utilisez kubectl drain <node> --ignore-daemonsets avant les redémarrages planifiés, puis kubectl uncordon après. Pour les redémarrages non planifiés, assurez-vous que les pods sont résilients et disposent de budgets de perturbation appropriés.
- Laisser les réglages de débogage activés
Pourquoi cela arrive : Augmenter la verbosité ou activer des ports non sécurisés pour le débogage et oublier de revenir en arrière. Comment l’éviter : Documentez toute modification temporaire de configuration avec une date d’échéance, utilisez la gestion de configuration pour garantir le retour en arrière et auditez périodiquement les réglages des nœuds.
- Ne pas sauvegarder la configuration avant les modifications
Pourquoi cela arrive : Excès de confiance ou absence de processus. Comment l’éviter : Créez toujours une sauvegarde horodatée : sudo cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.$(date +%Y%m%d). Testez la procédure de récupération dans un environnement hors production.
Liste de contrôle opérationnelle
Une liste de contrôle concise pour les opérations Kubelet, avec un responsable désigné et une fréquence de révision.
| Tâche | Commande / Action | Résultat attendu | Responsable | Fréquence de révision |
|---|---|---|---|---|
| Vérifier la version de Kubelet | kubelet --version | La version correspond à la base du cluster (par ex., v1.28.2) | Priya Shah, Responsable Ingénierie | Mensuelle |
| Vérifier les conditions du nœud | kubectl describe node <node-name> | Toutes les conditions sont False sauf Ready=True | Marcus Chen, Ingénieur DevOps | Hebdomadaire |
| Inspecter les journaux de Kubelet | sudo journalctl -u kubelet -n 100 | Aucune erreur répétée ; aucun message Failed to | Elena Rodriguez, SRE | Quotidienne (automatisée) |
| Examiner la configuration effective | kubelet --config /var/lib/kubelet/config.yaml --dump-config | La configuration correspond à l’état souhaité ; aucune surcharge inattendue | Priya Shah, Responsable Ingénierie | Mensuelle |
| Tester les seuils d’éviction | Simuler un stress mémoire sur un nœud de test | Les évictions se produisent uniquement aux seuils prévus ; les pods récupèrent | Marcus Chen, Ingénieur DevOps | Trimestrielle |
| Sauvegarder la configuration | sudo cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak | Le fichier de sauvegarde existe et est lisible | Elena Rodriguez, SRE | Avant tout changement |
| Surveiller l’expiration des certificats | sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates | Certificat valide pour >30 jours | Priya Shah, Responsable Ingénierie | Mensuelle |
Chaque élément a un seul responsable, et non un groupe, pour garantir la responsabilisation. Les révisions ont lieu selon un calendrier ou dans le cadre de la gestion des changements.
Conclusion
Les concepts avancés de Kubelet, à savoir la gestion de la configuration, les diagnostics et la récupération après défaillance, exigent une discipline opérationnelle rigoureuse. En suivant les pratiques décrites ici, vous pouvez réduire les temps d’arrêt, améliorer la stabilité des nœuds et résoudre efficacement les problèmes. Commencez toujours par l’observation, effectuez des modifications ciblées avec des sauvegardes vérifiées et documentez les chemins de récupération. La liste de contrôle opérationnelle fournit une base pour la responsabilisation de l’équipe et l’amélioration continue.
Pour les prochaines étapes, choisissez une vérification à faible risque de cet article, comme la vérification de la configuration effective de Kubelet avec --dump-config, et intégrez-la à votre routine. Mettez en place des alertes de surveillance pour les conditions du nœud et l’expiration des certificats. À mesure que vous gagnez en confiance, étendez le réglage des seuils d’éviction et l’optimisation de l’allocation des ressources. N’oubliez pas qu’un flux de travail fiable rend les défaillances visibles, protège les valeurs sensibles et limite les modifications à la ressource prévue.