Come risolvere gli errori della porta 10250 di kubelet
Scopri come risolvere "address already in use" durante kubeadm init e i blocchi del firewall che impediscono kubectl logs, exec e metrics-server.
Che cos'è la porta 10250
La porta 10250 espone l'API del kubelet e ogni errore che la cita indica uno di due problemi opposti. Oppure la porta è già occupata, quindi kubeadm init non riesce ad avviarsi. Oppure nessuno riesce a raggiungere la porta, quindi kubectl logs e kubectl exec falliscono su un nodo che, per il resto, sembra perfettamente integro.
Il kubelet è l'agente che Kubernetes esegue su ogni nodo. Avvia i container e ne comunica lo stato al control plane. Inoltre resta in ascolto sulla porta TCP 10250 ed espone un'API HTTPS utilizzata dal control plane. L'API server apre una connessione a questa porta quando si eseguono kubectl logs, kubectl exec, kubectl attach o kubectl port-forward. metrics-server interroga /metrics/resource sulla stessa porta; è questo che consente a kubectl top node di funzionare.
L'API richiede l'autenticazione. kubeadm disabilita l'accesso anonimo e configura il kubelet per utilizzare la CA del cluster (certificate authority), quindi una richiesta senza credenziali restituisce Unauthorized invece di fornire una shell all'interno di uno dei container. Questo dettaglio è importante anche perché rappresenta il modo più rapido per verificare che la porta sia raggiungibile. Se il concetto di porta non ti è ancora familiare, che cos'è realmente una porta in Linux descrive il modello utilizzato da questa guida.
Entrambe le modalità di errore dipendono dallo stesso requisito. La porta 10250 deve essere libera prima dell'avvio del kubelet e raggiungibile dal control plane dopo l'avvio del servizio.
Quale dei due problemi hai
Esegui questi comandi sul nodo interessato. Tutti i comandi riportati di seguito devono essere eseguiti da te sul tuo server.
sudo ss -lntp | grep 10250
sudo systemctl status kubelet --no-pagerss -lntp elenca i socket TCP in ascolto e il processo associato a ciascuno. -l indica che il socket è in ascolto, -n mantiene le porte in formato numerico, -t limita l’output a TCP e -p mostra il processo proprietario. Quest’ultimo flag richiede i privilegi di root. In caso contrario, la colonna del processo resta vuota e non fornisce informazioni utili.
Una riga che termina con users:(("kubelet",pid=1043,fd=23)) indica che kubelet è in esecuzione e occupa la porta. Se ti aspettavi che la porta fosse libera, hai trovato la causa. Se ss non restituisce alcun output e il control plane non riesce ancora a raggiungere questo nodo, il firewall non è ancora coinvolto: non c’è alcun servizio in ascolto sulla porta. Verifica perché kubelet non è in esecuzione prima di modificare qualsiasi regola.
systemctl status kubelet completa il quadro. active (running) con un’ora di avvio risalente a pochi minuti prima è normale. Anche un kubelet che si riavvia ogni pochi secondi prima dell’esecuzione di kubeadm init o kubeadm join è un comportamento normale: l’unità fornita dal pacchetto viene avviata al momento dell’installazione, non trova alcuna configurazione e termina. La documentazione upstream descrive questo ciclo di arresto e riavvio come previsto, mentre kubelet attende che kubeadm gli indichi cosa fare. Se il comportamento di riavvio di systemd non ti è familiare, come funzionano i tipi di servizio e le policy di riavvio di systemd fornisce il contesto per questa sezione.
Perché la porta 10250 risulta già in uso quando viene eseguito kubeadm init
kubeadm init esegue i controlli preliminari prima di scrivere dati su disco. Uno di questi controlli tenta di associare ogni porta necessaria al control plane e si interrompe con un errore che indica la porta 10250 quando l'associazione non riesce. Non è un bug. kubeadm rifiuta di creare un secondo cluster sui resti del primo.
In pratica, le cause sono quattro:
- Un precedente
kubeadm initokubeadm joininterrotto prima del completamento. kubelet ha già ricevuto una configurazione, quindi è in esecuzione e occupa la porta. - Un
kubeadm resetavviato ma non completato. Il reset arresta kubelet, ma non disabilita l'unità; al riavvio successivo il listener viene quindi riattivato. - k3s o un'altra distribuzione Kubernetes installata sullo stesso server. k3s include kubelet e anche questo kubelet si associa alla porta 10250.
- Il pacchetto
kubeletinstallato da apt e avviato dalla relativa unità systemd, su un server in cui non è ancora stato eseguito kubeadm.
Identifica la causa prima di modificare qualsiasi impostazione:
sudo ss -lntp 'sport = :10250'
systemctl list-units --type=service --state=running | grep -Ei 'kubelet|k3s|k0s'Se il listener appartiene a k3s, arrestalo e stabilisci quale cluster vuoi effettivamente utilizzare. k3s e kubeadm non possono condividere lo stesso server, perché utilizzano le stesse porte e la stessa directory CNI (container network interface). Il programma di installazione di k3s lascia uno script di disinstallazione in /usr/local/bin/k3s-uninstall.sh su un nodo server e in k3s-agent-uninstall.sh su un nodo agent.
Perché terminare kubelet non libera la porta
sudo pkill kubelet libera la porta 10250 per circa dieci secondi. L’unità fornita dal pacchetto definisce una policy di riavvio, quindi systemd avvia una nuova istanza di kubelet, che si associa nuovamente alla stessa porta. Puoi verificare direttamente la policy:
systemctl show kubelet -p Restart -p RestartSec
sudo systemctl stop kubelet
sudo ss -lntp | grep 10250Restart=always con RestartSec=10 è la configurazione fornita dall’unità. Per questo kill sembra funzionare, ma poi smette di funzionare. systemctl stop è il modo corretto per liberare la porta, perché systemd non riavvia un’unità che hai arrestato esplicitamente.
Liberare la porta non è comunque sufficiente su un nodo che contiene una parte del cluster. /var/lib/kubelet/config.yaml, i certificati presenti in /etc/kubernetes/pki e gli eventuali manifest degli static pod in /etc/kubernetes/manifests sono ancora presenti. I successivi controlli preliminari rilevano quei file e, se forzi il superamento dei controlli, ottieni un cluster i cui certificati non corrispondono alla configurazione. Esegui invece correttamente il reset del nodo.
Ripristinare il nodo in modo pulito
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 salta la richiesta di conferma. Il reset tenta di annullare le modifiche apportate da init o join. Rimuove i file e la configurazione locali, rimuove il membro etcd locale su un nodo del control plane, pulisce i certificati in /etc/kubernetes/pki e rimuove la configurazione e i manifest di kubelet.
La documentazione specifica chiaramente cosa resta dopo il reset e ciascun elemento può causare problemi. Il reset non pulisce /etc/cni/net.d, quindi la vecchia configurazione del plugin CNI rimane e il nuovo cluster la utilizza. Non rimuove alcuna regola iptables, nftables o IPVS applicata da kube-proxy all'host. Non interviene su $HOME/.kube, quindi kubectl continua a comunicare con un cluster che non esiste più e restituisce errori relativi ai certificati che possono sembrare un problema nuovo.
Le regole residue per i pacchetti sono l'aspetto più problematico. Svuotare manualmente le tabelle rimuove anche le regole installate da ufw, perché su Ubuntu ufw utilizza lo stesso backend. Il server rimane quindi senza filtraggio finché non esegui sudo ufw reload. Se il nodo deve essere ricostruito, riavvialo dopo il reset. Il riavvio rimuove le regole runtime aggiunte da kube-proxy e richiede meno tempo rispetto alla risoluzione dei problemi causati da un ruleset svuotato solo parzialmente. Perché le regole iptables e le regole nftables compaiono nell'output reciproco spiega cosa accade a un livello inferiore.
L'ultimo comando ss dovrebbe non produrre alcun output. Se non è in ascolto alcun servizio sulle porte 10250, 6443 o 2379, il nodo è pronto per un nuovo kubeadm init.
Timeout di kubectl logs e kubectl exec sulla porta 10250
Questa è la segnalazione opposta e non si presenta come un problema di porte. Il cluster si avvia. I nodi risultano Ready. I pod sono in esecuzione. Poi un comando non riesce:
Error from server: Get "https://10.0.0.12:10250/containerLogs/default/web-0/web": dial tcp 10.0.0.12:10250: i/o timeoutLeggete il messaggio partendo dalla fine. Il server API ha tentato di aprire una connessione TCP verso il nodo sulla porta 10250, ma non ha ricevuto risposta. i/o timeout indica che i pacchetti sono stati scartati senza risposta, quindi qualcosa li filtra: il firewall dell'host sul nodo oppure il firewall di rete separato del provider, configurato nel pannello di controllo. connect: connection refused nella stessa posizione indica il caso opposto. Il pacchetto è arrivato, ma non c'era alcun processo in ascolto: il kubelet è arrestato. È la stessa coppia di cause descritta in connessione rifiutata e connessione scaduta, osservata qui su una porta diversa.
I nodi restano Ready durante tutto questo, perché lo stato dei nodi viaggia nella direzione opposta. Il kubelet si connette in uscita al server API sulla porta 6443 e invia il proprio heartbeat; per farlo non serve alcuna connessione in ingresso sulla porta 10250. Un blocco della porta 10250 consente quindi al cluster di pianificare normalmente i pod, ma impedisce soltanto logs, exec, port-forward e metriche.
kubectl top node che restituisce error: Metrics API not available indica lo stesso problema visto attraverso metrics-server, il cui log specifica il nodo e la porta:
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 timeoutTestare il percorso prima di modificare una regola del firewall
Eseguire questo comando da un nodo del control plane, verso l'indirizzo del 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 apre una connessione, la chiude e stampa succeeded! quando la porta accetta la connessione. Il comando curl è il test più indicato, perché dimostra che kubelet sta fornendo il servizio invece di dimostrare soltanto che una porta è aperta. Stampa 401. Questo è il risultato corretto: l'handshake TLS (transport layer security) è stato completato, quindi kubelet ha rifiutato una richiesta non autenticata, come previsto. -k disabilita il controllo del certificato; in questo caso è corretto, perché si sta testando il percorso e non la catena di attendibilità.
Una pausa prolungata che termina con un timeout indica che i pacchetti vengono scartati. curl: (7) Failed to connect restituito immediatamente indica che la porta è chiusa su un host raggiungibile. Eseguire il test dal nodo del control plane, non dal laptop, perché in questo caso conta soltanto l'accesso dal control plane.
Porte necessarie per il control plane e per un worker
Queste sono le porte in ingresso indicate dal progetto upstream. Su un nodo del control plane, la porta TCP 6443 è utilizzata dall'API server ed è aperta a tutto ciò che viene eseguito su kubectl. Le porte TCP da 2379 a 2380 sono utilizzate dall'API client e peer di etcd, dall'API server e da etcd stesso. La porta TCP 10250 è utilizzata dall'API di kubelet, dal nodo stesso e dal control plane. La porta TCP 10259 è utilizzata da kube-scheduler, mentre la porta TCP 10257 è utilizzata da kube-controller-manager; entrambe sono utilizzate soltanto dal nodo stesso.
Su un nodo worker, la porta TCP 10250 è utilizzata dall'API di kubelet, dal nodo stesso e dal control plane. La porta TCP 10256 è utilizzata da kube-proxy, dal nodo stesso e dai load balancer che eseguono i controlli di integrità. Le porte TCP e UDP da 30000 a 32767 sono utilizzate dai servizi NodePort. Questo è l'intervallo predefinito ed è raggiungibile da chiunque abbia bisogno di questi servizi.
Il plugin CNI aggiunge altre porte a questo elenco, che qui non sono riportate. Flannel e Calico in modalità VXLAN richiedono la porta UDP 4789 tra i nodi. Calico con BGP richiede la porta TCP 179. Consultare la documentazione del plugin e aprire queste porte tra i nodi. In caso contrario, i pod su nodi diversi non comunicheranno tra loro anche se tutte le porte di questa sezione sono aperte.
Aprire la porta 10250 senza esporla a Internet
L'API kubelet può avviare un processo all'interno di qualsiasi container presente sul nodo. Considera una porta 10250 aperta come accesso root al nodo e limita l'accesso in base all'indirizzo sorgente. Non consentirlo mai da qualsiasi origine.
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 numberedSostituisci 10.0.0.0/24 con la rete condivisa dai nodi. ufw status numbered elenca le regole attive con un indice, così puoi eliminare quella errata con sudo ufw delete <number>. Le nozioni di base di ufw per un VPS illustra le regole di ordinamento che determinano quale delle voci inserite viene effettivamente applicata.
Un'impostazione di ufw può compromettere Kubernetes da sola. Il traffico dei pod che attraversa il nodo viene inoltrato, non consegnato localmente, e ufw elimina per impostazione predefinita i pacchetti inoltrati. Imposta DEFAULT_FORWARD_POLICY="ACCEPT" in /etc/default/ufw ed esegui sudo ufw reload. Senza questa impostazione, la porta 10250 può restare completamente esposta e il traffico tra pod su nodi diversi continua a non funzionare.
Controlla anche il firewall del provider. La maggior parte dei pannelli VPS dispone di un firewall a livello di rete che si trova davanti al server ed è invisibile a ufw status. Una regola aggiunta sul nodo non cambia nulla se il pacchetto non arriva mai al server.
Quando la porta è raggiungibile ma la richiesta continua a non riuscire
Alcuni errori sulla porta 10250 vengono restituiti immediatamente invece di lasciare la connessione in attesa. Questo indica che la connessione è riuscita, ma la richiesta è stata rifiutata. x509: certificate signed by unknown authority nel log di metrics-server indica che kubelet sta fornendo un certificato autofirmato che lo scraper non considera attendibile. In genere, è necessario abilitare la rotazione dei certificati di servizio di kubelet, in modo che il cluster CA firmi il certificato, quindi approvare la richiesta di firma del certificato. In alternativa, in un cluster di laboratorio è possibile accettare il rischio ed eseguire metrics-server con --kubelet-insecure-tls.
Un messaggio che contiene Forbidden insieme a nodes/proxy o nodes/metrics indica un errore RBAC (controllo degli accessi basato sui ruoli). Il chiamante ha raggiunto kubelet. Kubelet ha chiesto al server API se quell'identità può usare la sotto-risorsa, ma la risposta è stata negativa. Correggere il ClusterRole del chiamante. Nessuna modifica al firewall sarà utile, perché il traffico non è stato bloccato.
Se ti serve soltanto un piccolo cluster
Se riscontri questi errori mentre configuri kubeadm per la prima volta su un singolo VPS, valuta se kubeadm sia davvero necessario. Un cluster k3s a nodo singolo su un VPS fornisce un'API Kubernetes funzionante con un solo comando, con kubelet, kube-proxy e una CNI già integrati. Anche in questo caso la porta 10250 è presente e valgono le stesse regole, ma non devi più assemblare manualmente il control plane.
FAQ
A cosa serve la porta 10250 in Kubernetes?
È l'API HTTPS autenticata del kubelet presente su ogni nodo, sia del control plane sia worker. L'API server si connette a questa porta per kubectl logs, kubectl exec, kubectl attach e kubectl port-forward; metrics-server usa invece la porta per raccogliere /metrics/resource e fornire kubectl top. Lo stato dei nodi non usa questa porta, perché il kubelet invia il proprio heartbeat in uscita all'API server sulla porta 6443. Per questo, se la porta 10250 è bloccata, i nodi risultano Ready, mentre la lettura dei log e l'esecuzione dei comandi nei container non funzionano.
Come posso verificare quale processo è in ascolto sulla porta 10250?
Esegui sudo ss -lntp | grep 10250 sul nodo. Il campo users:((...)) alla fine della riga identifica il processo e il relativo PID. sudo è importante, perché senza root la colonna del processo rimane vuota. Se il processo proprietario è il kubelet, sudo systemctl status kubelet --no-pager indica se il kubelet funziona correttamente o se viene riavviato continuamente. Se il processo proprietario è k3s, sul server sono installate due distribuzioni Kubernetes e devi rimuoverne una.
Devo aprire la porta 10250 nel firewall?
Sì, per le comunicazioni tra i nodi. Il control plane deve poter raggiungere la porta 10250 su ogni nodo, incluso se stesso; in caso contrario, log, exec, port-forward e metriche non funzionano. Limita l'accesso in base all'origine alla rete condivisa dai nodi, ad esempio sudo ufw allow from 10.0.0.0/24 to any port 10250 proto tcp. Non esporre la porta a Internet: qualsiasi client che riesca ad autenticarsi su questa porta può eseguire un processo in qualunque container del nodo.
Perché kubectl logs non funziona per i pod presenti su un solo nodo?
Perché il blocco riguarda quel nodo specifico e l'API server si connette al nodo che ospita il pod. Leggi il testo dell'errore: contiene l'indirizzo IP del nodo che il server ha tentato di raggiungere. Esegui quindi nc -zv <node-ip> 10250 da un nodo del control plane. Un timeout indica un problema nel firewall del nodo o nel firewall di rete del provider. connection refused indica che il kubelet non è in esecuzione su quel nodo; controlla quindi systemctl status kubelet direttamente sul nodo.