Résoudre les erreurs du port 10250 de kubelet sur Ubuntu
Le port 10250 est déjà utilisé ou bloqué par le pare-feu ? Corrigez l’erreur « address already in use » de kubeadm init et rétablissez kubectl logs et exec.
À quoi sert le port 10250
Le port 10250 correspond à l’API du kubelet. Toute erreur qui le mentionne indique l’un de deux problèmes opposés. Soit un autre processus utilise déjà le port et kubeadm init refuse de démarrer. Soit rien ne peut atteindre le port et kubectl logs et kubectl exec échouent contre un nœud qui semble pourtant parfaitement sain.
Le kubelet est l’agent que Kubernetes exécute sur chaque nœud. Il démarre les conteneurs et renvoie leur état au control plane. Il écoute également sur le port TCP 10250 et fournit une API HTTPS appelée par le control plane. L’API server ouvre une connexion vers ce port lorsque vous exécutez kubectl logs, kubectl exec, kubectl attach ou kubectl port-forward. metrics-server récupère les métriques via /metrics/resource sur le même port, ce qui permet à kubectl top node de fonctionner.
Cette API est authentifiée. kubeadm désactive l’accès anonyme et configure le kubelet pour utiliser l’autorité de certification du cluster (certificate authority). Une requête sans identifiants reçoit donc Unauthorized, et non un shell à l’intérieur de l’un de vos conteneurs. Gardez ce point à l’esprit : c’est également le moyen le plus rapide de vérifier que le port est accessible. Si les ports vous sont encore peu familiers, ce qu’est réellement un port sous Linux présente le modèle utilisé dans ce guide.
Les deux modes d’échec découlent d’une même exigence. Le port 10250 doit être libre avant le démarrage du kubelet et accessible depuis le control plane une fois celui-ci démarré.
Quel est le problème que vous rencontrez ?
Exécutez ces commandes sur le nœud concerné. Vous exécutez vous-même chacune d’elles sur votre propre serveur.
sudo ss -lntp | grep 10250
sudo systemctl status kubelet --no-pagerss -lntp répertorie les sockets TCP en écoute et le processus associé à chacun. -l signifie que le socket est en écoute, -n conserve les ports au format numérique, -t limite l’affichage à TCP et -p affiche le processus propriétaire. Ce dernier flag nécessite les droits root. Sinon, la colonne du processus reste vide et la commande ne fournit aucune information utile.
Une ligne qui se termine par users:(("kubelet",pid=1043,fd=23)) signifie que le kubelet fonctionne et utilise le port. Si vous pensiez que le port devait être libre, vous avez trouvé la cause. Si ss n’affiche absolument rien et que le control plane ne peut toujours pas joindre ce nœud, aucun pare-feu n’intervient encore : aucun service n’écoute le port. Déterminez pourquoi le kubelet est arrêté avant de modifier une règle.
systemctl status kubelet fournit l’autre moitié du diagnostic. active (running) avec une heure de démarrage remontant à quelques minutes est normal. Il est également normal que le kubelet redémarre toutes les quelques secondes avant l’exécution de kubeadm init ou kubeadm join : l’unité fournie par le paquet démarre au moment de l’installation, ne trouve aucune configuration, puis se termine. La documentation upstream indique que cette boucle de crash est un comportement attendu pendant que le kubelet attend que kubeadm lui indique quoi faire. Si le comportement de redémarrage de systemd ne vous est pas familier, consultez le fonctionnement des types de services et des politiques de redémarrage de systemd pour le contexte de cette section.
Pourquoi le port 10250 est-il déjà utilisé lors de l’exécution de kubeadm init
kubeadm init effectue des contrôles préalables avant d’écrire quoi que ce soit sur le disque. L’un de ces contrôles tente d’écouter sur chaque port dont le control plane a besoin. Il s’arrête avec une erreur indiquant le port 10250 lorsque cette opération échoue. Ce n’est pas un bug. kubeadm refuse de construire un deuxième cluster sur les restes du premier.
En pratique, quatre causes sont possibles :
- Une précédente exécution de
kubeadm initou dekubeadm joinqui s’est interrompue en cours de route. Le kubelet a déjà reçu une configuration. Il fonctionne donc et occupe le port. - Un
kubeadm resetqui a été démarré mais n’a pas été terminé. Reset arrête le kubelet, mais ne désactive pas l’unité. Au redémarrage suivant, celle-ci relance donc le listener. - k3s ou une autre distribution Kubernetes installée sur le même serveur. k3s intègre un kubelet, qui écoute lui aussi sur le port 10250.
- Le paquet
kubeletinstallé par apt et démarré par sa propre unité systemd, sur un serveur où vous n’avez pas encore exécuté kubeadm.
Déterminez d’abord laquelle de ces causes s’applique avant de modifier quoi que ce soit :
sudo ss -lntp 'sport = :10250'
systemctl list-units --type=service --state=running | grep -Ei 'kubelet|k3s|k0s'Si le listener appartient à k3s, arrêtez-vous et déterminez quel cluster vous souhaitez réellement utiliser. k3s et kubeadm ne peuvent pas partager un serveur, car ils utilisent les mêmes ports et le même répertoire CNI (container network interface). L’installateur k3s laisse un script de désinstallation à l’emplacement /usr/local/bin/k3s-uninstall.sh sur un nœud serveur et à l’emplacement k3s-agent-uninstall.sh sur un nœud agent.
Pourquoi tuer kubelet ne libère pas le port
sudo pkill kubelet libère le port 10250 pendant environ dix secondes. L’unité fournie définit une stratégie de redémarrage. systemd lance donc un nouveau kubelet, qui se lie de nouveau au même port. Vous pouvez vérifier cette stratégie vous-même :
systemctl show kubelet -p Restart -p RestartSec
sudo systemctl stop kubelet
sudo ss -lntp | grep 10250Restart=always avec RestartSec=10 correspond à la configuration fournie par l’unité. C’est exactement pourquoi kill semble fonctionner, puis échoue. systemctl stop est la bonne méthode pour libérer le port, car systemd cesse de redémarrer une unité que vous lui avez demandé d’arrêter.
Un port libre ne suffit pas sur un nœud qui héberge la moitié d’un cluster. /var/lib/kubelet/config.yaml, les certificats sous /etc/kubernetes/pki et les manifests de static pods dans /etc/kubernetes/manifests sont toujours présents. Les vérifications preflight ultérieures butent sur ces fichiers. Forcer le passage de ces vérifications vous laisse avec un cluster dont les certificats ne correspondent pas à la configuration. Réinitialisez correctement le nœud.
Réinitialiser proprement le nœud
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
rm -rf $HOME/.kube
sudo systemctl stop kubelet
sudo ss -lntp | grep -E '10250|6443|2379'-f ignore l’invite de confirmation. La réinitialisation tente de revenir à l’état antérieur aux opérations effectuées par init ou join. Elle supprime les fichiers et la configuration locaux, supprime le membre etcd local sur un nœud du control plane, nettoie les certificats dans /etc/kubernetes/pki et supprime la configuration ainsi que les manifests du kubelet.
La documentation précise ce que la réinitialisation laisse en place, et chacun de ces éléments pose régulièrement problème. Elle ne nettoie pas /etc/cni/net.d. L’ancienne configuration du plugin CNI reste donc présente, et votre nouveau cluster la lit. Elle ne supprime aucune règle iptables, nftables ou IPVS appliquée à l’hôte par kube-proxy. Elle ne modifie pas $HOME/.kube. Ainsi, kubectl continue de communiquer avec un cluster qui n’existe plus et renvoie des erreurs de certificat qui ressemblent à un nouveau problème.
Les règles de filtrage restantes sont la partie la plus délicate. Vider les tables manuellement supprime aussi les règles installées par ufw, car ufw utilise le même backend sur Ubuntu. Le serveur reste alors sans filtrage jusqu’à l’exécution de sudo ufw reload. Sur un nœud que vous allez de toute façon reconstruire, redémarrez après la réinitialisation. Le redémarrage supprime les règles runtime ajoutées par kube-proxy et prend moins de temps que le dépannage d’un jeu de règles partiellement vidé. Pourquoi les règles iptables et nftables apparaissent dans la sortie des unes et des autres explique ce qui se passe en arrière-plan.
La dernière commande ss ne doit rien afficher. Si aucun processus n’écoute sur 10250, 6443 ou 2379, le nœud est prêt pour un nouveau kubeadm init.
Pourquoi kubectl logs et kubectl exec expirent sur le port 10250
C’est le problème inverse, et il ne se présente pas comme un problème de port. Le cluster démarre. Les nœuds sont Ready. Les pods s’exécutent. Puis une commande échoue :
Error from server: Get "https://10.0.0.12:10250/containerLogs/default/web-0/web": dial tcp 10.0.0.12:10250: i/o timeoutLisez ce message en partant de la fin. L’API server a tenté d’ouvrir une connexion TCP vers le nœud sur le port 10250, mais n’a reçu aucune réponse. i/o timeout signifie que les paquets ont été silencieusement rejetés. Quelque chose les filtre : le pare-feu de l’hôte sur le nœud ou le pare-feu réseau distinct de votre fournisseur, dans le panneau de contrôle. connect: connection refused au même endroit signifie l’inverse. Le paquet est arrivé, mais aucun processus n’était en écoute. Le kubelet est donc arrêté. Il s’agit de la même paire de causes que celle décrite dans connexion refusée ou connexion expirée, ici sur un autre port.
Les nœuds restent Ready pendant tout ce temps, car l’état des nœuds circule dans l’autre sens. Le kubelet se connecte vers l’extérieur à l’API server sur le port 6443 et envoie lui-même son heartbeat. Cela ne nécessite aucune connexion entrante sur le port 10250. Ainsi, un port 10250 bloqué laisse le cluster planifier les pods normalement, mais fait échouer uniquement logs, exec, port-forward et les métriques.
kubectl top node qui répond error: Metrics API not available correspond au même problème observé via metrics-server, dont le journal indique le nœud et le port :
unable to fully scrape metrics from node worker-1: unable to fetch metrics from node worker-1: Get "https://10.0.0.12:10250/metrics/resource": dial tcp 10.0.0.12:10250: i/o timeoutTester le chemin avant de modifier une règle de firewall
Exécutez cette commande depuis un nœud du control plane, vers l’adresse du worker :
nc -zv 10.0.0.12 10250
curl -sk -o /dev/null -w '%{http_code}\n' https://10.0.0.12:10250/healthznc -z ouvre une connexion, la ferme, puis affiche succeeded! lorsque le port accepte la connexion. La commande curl est le meilleur test, car elle vérifie que le kubelet répond, et pas seulement qu’un port est ouvert. Elle affiche 401. C’est le résultat attendu : le handshake TLS (transport layer security) s’est terminé, puis le kubelet a rejeté une requête non authentifiée, comme il doit le faire. -k désactive la vérification du certificat, ce qui convient ici, car vous testez le chemin réseau, pas la chaîne de confiance.
Une longue attente qui se termine par un timeout signifie que les paquets sont rejetés. Le retour instantané de curl: (7) Failed to connect signifie que le port est fermé sur un hôte joignable. Effectuez le test depuis le nœud du control plane, et non depuis votre ordinateur portable, car seul l’accès du control plane est pertinent ici.
Ports requis sur un control plane et sur un worker
Voici les ports entrants listés par la documentation amont. Sur un nœud control plane, ouvrez le port TCP 6443 pour l’API server à tout ce qui exécute kubectl. Les ports TCP 2379 à 2380 servent à l’API client et peer d’etcd, utilisée par l’API server et par etcd lui-même. Le port TCP 10250 sert à l’API du kubelet, utilisée par le nœud lui-même et par le control plane. Les ports TCP 10259 pour kube-scheduler et TCP 10257 pour kube-controller-manager sont utilisés uniquement par le nœud lui-même.
Sur un nœud worker, le port TCP 10250 sert à l’API du kubelet, utilisée par le nœud lui-même et par le control plane. Le port TCP 10256 sert à kube-proxy, utilisé par le nœud lui-même et par les load balancers qui effectuent des health checks. Les ports TCP et UDP 30000 à 32767 servent aux services NodePort. Il s’agit de la plage par défaut, accessible par les clients qui ont besoin de ces services.
Votre plugin CNI ajoute ses propres ports à cette liste. Ils n’y figurent pas. Flannel et Calico en mode VXLAN utilisent le port UDP 4789 entre les nœuds. Calico avec BGP utilise le port TCP 179. Consultez la documentation de votre plugin et ouvrez ces ports entre les nœuds. Sinon, les pods situés sur des nœuds différents ne pourront pas communiquer, même si tous les ports de cette section sont ouverts.
Ouvrir le port 10250 sans l’exposer à Internet
L’API kubelet peut démarrer un processus dans n’importe quel conteneur de ce nœud. Considérez qu’un port 10250 ouvert équivaut à un accès root au nœud et limitez l’accès selon l’adresse source. Ne l’autorisez jamais depuis n’importe quelle adresse.
sudo ufw allow from 10.0.0.0/24 to any port 10250 proto tcp comment 'kubelet API'
sudo ufw allow from 10.0.0.0/24 to any port 10256 proto tcp comment 'kube-proxy'
sudo ufw status numberedRemplacez 10.0.0.0/24 par le réseau partagé par vos nœuds. ufw status numbered affiche les règles actives avec un index, afin que vous puissiez supprimer une règle incorrecte avec sudo ufw delete <number>. Les bases d’ufw pour un VPS explique les règles d’ordre qui déterminent quelle entrée s’applique réellement.
Un paramètre d’ufw suffit à perturber Kubernetes. Le trafic des pods qui traverse le nœud est transféré, et n’est pas distribué localement ; ufw bloque les paquets transférés par défaut. Définissez DEFAULT_FORWARD_POLICY="ACCEPT" dans /etc/default/ufw, puis exécutez sudo ufw reload. Sans ce réglage, le port 10250 peut être totalement exposé et le trafic entre pods sur des nœuds différents échoue quand même.
Vérifiez également le firewall de votre fournisseur. La plupart des interfaces VPS disposent d’un firewall réseau situé en amont du serveur, qui est invisible pour ufw status. Une règle ajoutée sur le nœud ne change rien si le paquet n’atteint jamais le serveur.
Lorsque le port est accessible, mais que la requête échoue quand même
Certaines erreurs sur 10250 sont renvoyées immédiatement au lieu de rester bloquées. Cela indique que la connexion a abouti, mais que la requête a été rejetée. x509: certificate signed by unknown authority dans le journal de metrics-server signifie que le kubelet présente un certificat auto-signé que le scraper ne reconnaît pas. La solution habituelle consiste à activer la rotation des certificats de service du kubelet, afin que l’autorité de certification du cluster signe le certificat, puis à approuver la demande de signature de certificat. Sur un cluster de laboratoire, vous pouvez aussi accepter le risque et exécuter metrics-server avec --kubelet-insecure-tls.
Un message contenant Forbidden avec nodes/proxy ou nodes/metrics indique un problème RBAC (contrôle d’accès basé sur les rôles). L’appelant a atteint le kubelet. Le kubelet a demandé au serveur d’API si cette identité pouvait utiliser la sous-ressource, et la réponse était négative. Corrigez le ClusterRole de l’appelant. Aucune modification du pare-feu ne résoudra le problème, car rien n’a été bloqué.
Si vous avez seulement besoin d’un petit cluster
Si ces erreurs apparaissent lors de la mise en place initiale de kubeadm sur un VPS unique, demandez-vous si kubeadm est réellement nécessaire. Un cluster k3s à nœud unique sur un VPS fournit une API Kubernetes fonctionnelle en une seule commande, avec le kubelet, kube-proxy et un CNI déjà configurés ensemble. Le port 10250 est également présent dans ce cas et les mêmes règles s’y appliquent, mais vous n’avez plus à assembler vous-même le control plane.
FAQ
À quoi sert le port 10250 dans Kubernetes ?
Il expose l’API HTTPS authentifiée du kubelet sur chaque nœud, qu’il s’agisse du control plane ou d’un worker. L’API server s’y connecte pour kubectl logs, kubectl exec, kubectl attach et kubectl port-forward, tandis que metrics-server y récupère /metrics/resource pour fournir kubectl top. L’état du nœud ne passe pas par ce port, car le kubelet envoie son heartbeat au serveur d’API sur le port 6443. C’est pourquoi le blocage de 10250 laisse les nœuds dans l’état Ready, alors que les commandes de consultation des logs et d’exécution échouent.
Comment trouver ce qui écoute sur le port 10250 ?
Exécutez sudo ss -lntp | grep 10250 sur le nœud. Le champ users:((...)) à la fin de la ligne indique le processus et son PID. sudo est nécessaire, car sans root la colonne du processus reste vide. Si le propriétaire est le kubelet, sudo systemctl status kubelet --no-pager vous indique s’il fonctionne normalement ou s’il redémarre en boucle. Si le propriétaire est k3s, deux distributions Kubernetes sont installées sur le même serveur et vous devez en supprimer une.
Dois-je ouvrir le port 10250 dans mon firewall ?
Oui, entre vos nœuds. Le control plane doit pouvoir atteindre le port 10250 sur chaque nœud, y compris lui-même. Sinon, les logs, exec, port-forward et les métriques échouent. Limitez les sources au réseau partagé par vos nœuds, par exemple sudo ufw allow from 10.0.0.0/24 to any port 10250 proto tcp. Ne l’ouvrez pas sur Internet : tout ce qui peut s’authentifier sur ce port peut exécuter un processus dans n’importe quel conteneur du nœud.
Pourquoi kubectl logs échoue-t-il uniquement pour les pods d’un nœud ?
Parce que le blocage concerne un seul nœud et que l’API server se connecte au nœud précis qui héberge le pod. Lisez le texte de l’erreur : il contient l’adresse IP du nœud que le serveur a tenté d’atteindre. Exécutez ensuite nc -zv <node-ip> 10250 depuis un nœud du control plane. Un timeout indique un problème de firewall sur ce nœud ou dans le firewall réseau de votre fournisseur. connection refused indique que le kubelet ne fonctionne pas sur ce nœud. Vérifiez donc systemctl status kubelet sur ce nœud.