SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-21

Kubelet port 10250: naprawa błędów na Ubuntu

Rozwiązanie problemu address already in use podczas kubeadm init oraz blokad firewalla uniemożliwiających kubectl logs i exec. Instrukcja konfiguracji portu 10250 w Kubernetes.

Czym jest port 10250

Port 10250 obsługuje API kubelet, a każdy błąd dotyczący tego portu wynika z jednego z dwóch przeciwstawnych problemów. Albo port jest już zajęty, przez co kubeadm init odmawia uruchomienia. Albo nikt nie może nawiązać połączenia z portem, przez co kubectl logs oraz kubectl exec kończą się niepowodzeniem w przypadku węzła, który poza tym wydaje się w pełni sprawny.

Kubelet to agent Kubernetes działający na każdym węźle. Uruchamia on kontenery i raportuje ich stan do płaszczyzny sterowania (control plane). Nasłuchuje również na porcie TCP 10250 i udostępnia API HTTPS, z którego korzysta płaszczyzna sterowania. Serwer API otwiera połączenie z tym portem, gdy uruchamiane są polecenia kubectl logs, kubectl exec, kubectl attach lub kubectl port-forward. Komponent metrics-server odpytuje /metrics/resource na tym samym porcie, co umożliwia działanie kubectl top node.

To API wymaga uwierzytelnienia. kubeadm wyłącza dostęp anonimowy i wskazuje kubeletowi certyfikat urzędu (CA) klastra, więc żądanie bez poświadczeń kończy się odpowiedzią Unauthorized, zamiast przyznaniem dostępu do powłoki wewnątrz jednego z kontenerów. Należy o tym pamiętać, ponieważ jest to również najszybszy sposób na sprawdzenie, czy port jest osiągalny. Jeśli pojęcia związane z portami są nowe, czym w rzeczywistości jest port w systemie Linux wyjaśnia model, na którym opiera się ten przewodnik.

Oba scenariusze awarii wynikają z jednego wymagania. Port 10250 musi być wolny przed uruchomieniem kubelet i osiągalny z poziomu płaszczyzny sterowania, gdy usługa już działa.

Z którym z dwóch problemów masz do czynienia

Wykonaj poniższe polecenia na danym węźle. Każde z poniższych poleceń uruchamiasz samodzielnie na własnym serwerze.

sudo ss -lntp | grep 10250
sudo systemctl status kubelet --no-pager

ss -lntp wyświetla nasłuchujące gniazda TCP wraz z procesem przypisanym do każdego z nich. -l oznacza nasłuchiwanie, -n wymusza wyświetlanie numerów portów, -t ogranicza wynik do protokołu TCP, -p pokazuje proces właściciela. Ta ostatnia flaga wymaga uprawnień root, w przeciwnym razie kolumna procesu będzie pusta i nie uzyskasz żadnych informacji.

Wiersz kończący się na users:(("kubelet",pid=1043,fd=23)) oznacza, że kubelet działa i zajmuje port. Jeśli oczekiwałeś, że port będzie wolny, to jest to rozwiązanie problemu. Jeśli ss nie wyświetla nic, a płaszczyzna sterowania (control plane) nadal nie może połączyć się z tym węzłem, oznacza to, że firewall nie jest jeszcze przyczyną, ponieważ na tym porcie nikt nie nasłuchuje. Dowiedz się, dlaczego kubelet nie działa, zanim zaczniesz modyfikować jakiekolwiek reguły.

systemctl status kubelet przedstawia drugą stronę zagadnienia. active (running) z czasem uruchomienia sprzed kilku minut jest stanem normalnym. Kubelet restartujący się co kilka sekund zanim uruchomisz kubeadm init lub kubeadm join również jest stanem normalnym: jednostka systemd uruchamia się w momencie instalacji, nie znajduje konfiguracji i kończy działanie. Dokumentacja upstream opisuje tę pętlę awarii jako oczekiwane zachowanie, podczas gdy kubelet czeka na instrukcje od kubeadm. Jeśli mechanizm restartu systemd jest niejasny, jak działają typy usług i polityki restartu systemd stanowi wprowadzenie do tej sekcji.

Dlaczego port 10250 jest już zajęty podczas uruchamiania kubeadm init

kubeadm init wykonuje testy wstępne przed zapisaniem jakichkolwiek danych na dysku. Jeden z tych testów próbuje powiązać każdy port wymagany przez płaszczyznę sterowania (control plane). Jeśli powiązanie się nie powiedzie, proces kończy się błędem wskazującym na port 10250. Nie jest to błąd oprogramowania. Jest to mechanizm zabezpieczający kubeadm przed budową drugiego klastra na pozostałościach pierwszego.

W praktyce przyczyną są zazwyczaj cztery sytuacje:

  • Wcześniejsza operacja kubeadm init lub kubeadm join, która zakończyła się niepowodzeniem w trakcie wykonywania. Komponent kubelet otrzymał już konfigurację, więc działa i zajmuje port.
  • Proces kubeadm reset, który został rozpoczęty, ale nieukończony. Polecenie reset zatrzymuje kubelet, ale nie wyłącza jednostki systemd, więc po ponownym uruchomieniu serwera proces ponownie nasłuchuje na porcie.
  • k3s lub inna dystrybucja Kubernetes zainstalowana na tym samym serwerze. k3s zawiera wbudowany kubelet, który również wiąże się z portem 10250.
  • Pakiet kubelet pobrany przez apt i uruchomiony przez własną jednostkę systemd na serwerze, na którym nie uruchomiono jeszcze kubeadm.

Przed wprowadzeniem jakichkolwiek zmian należy ustalić przyczynę:

sudo ss -lntp 'sport = :10250'
systemctl list-units --type=service --state=running | grep -Ei 'kubelet|k3s|k0s'

Jeśli proces nasłuchujący należy do k3s, należy zatrzymać działanie i zdecydować, który klaster ma pozostać. k3s oraz kubeadm nie mogą współdzielić jednego serwera, ponieważ wymagają tych samych portów oraz tego samego katalogu CNI (container network interface). Instalator k3s pozostawia skrypt odinstalowujący w lokalizacji /usr/local/bin/k3s-uninstall.sh na węźle serwera oraz k3s-agent-uninstall.sh na węźle agenta.

Dlaczego zabicie procesu kubelet nie zwalnia portu

sudo pkill kubelet zwalnia port 10250 na około dziesięć sekund. Dostarczona jednostka ma ustawioną politykę restartu, więc systemd uruchamia nowy proces kubelet, który ponownie wiąże ten sam port. Politykę tę można sprawdzić samodzielnie:

systemctl show kubelet -p Restart -p RestartSec
sudo systemctl stop kubelet
sudo ss -lntp | grep 10250

Restart=always wraz z RestartSec=10 to ustawienia domyślne jednostki, co jest bezpośrednią przyczyną, dla której kill wydaje się działać, a następnie przestaje. systemctl stop to właściwy sposób na zwolnienie portu, ponieważ systemd przestaje restartować jednostkę, której zatrzymanie zostało zlecone.

Wolny port to wciąż za mało na węźle, który obsługuje połowę klastra. /var/lib/kubelet/config.yaml, certyfikaty w /etc/kubernetes/pki oraz wszelkie manifesty statycznych podów w /etc/kubernetes/manifests nadal tam pozostają. Późniejsze testy wstępne (preflight checks) napotkają te pliki, a wymuszenie ich pominięcia doprowadzi do powstania klastra, którego certyfikaty nie są zgodne z konfiguracją. Zamiast tego należy poprawnie zresetować węzeł.

Czysty reset węzła

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'

Flaga -f pomija monit z prośbą o potwierdzenie. Polecenie reset podejmuje próbę przywrócenia stanu sprzed wykonania init lub join. Usuwa ono pliki lokalne i konfigurację, usuwa lokalnego członka etcd na węźle płaszczyzny sterowania (control plane), czyści certyfikaty w /etc/kubernetes/pki oraz usuwa konfigurację i manifesty kubelet.

Dokumentacja precyzyjnie określa, co pozostaje po resecie, a każdy z tych elementów bywa problematyczny. Proces nie czyści /etc/cni/net.d, więc stara konfiguracja wtyczki CNI pozostaje, a nowy klaster ją odczytuje. Nie czyści również żadnych reguł iptables, nftables ani IPVS, które kube-proxy zaaplikował na hoście. Nie ingeruje w $HOME/.kube, przez co kubectl nadal próbuje komunikować się z klastrem, który już nie istnieje, zwracając błędy certyfikatów, które wyglądają na nowy problem.

Pozostałe reguły pakietów są najbardziej kłopotliwe. Ręczne czyszczenie tablic usuwa również reguły zainstalowane przez ufw, ponieważ ufw w systemie Ubuntu korzysta z tego samego backendu. Powoduje to pozostawienie serwera bez ochrony, dopóki nie zostanie wykonane sudo ufw reload. W przypadku węzła, który i tak jest przebudowywany, po resecie należy wykonać restart systemu. Restart czyści reguły runtime dodane przez kube-proxy i zajmuje mniej czasu niż próba naprawy częściowo wyczyszczonego zestawu reguł. Dlaczego reguły iptables i nftables pojawiają się w wynikach swoich poleceń wyjaśnia mechanizmy działające w tle.

Ostatnie polecenie ss nie powinno zwrócić żadnych danych. Brak nasłuchiwania na portach 10250, 6443 lub 2379 oznacza, że węzeł jest gotowy na świeże kubeadm init.

Dlaczego polecenia kubectl logs oraz kubectl exec kończą się przekroczeniem czasu oczekiwania na porcie 10250

Jest to odwrotny problem, który nie jest sygnalizowany jako błąd portu. Klaster uruchamia się poprawnie. Węzły mają status Ready. Pody działają. Następnie jedno polecenie kończy się niepowodzeniem:

Error from server: Get "https://10.0.0.12:10250/containerLogs/default/web-0/web": dial tcp 10.0.0.12:10250: i/o timeout

Należy odczytać ten komunikat od końca. Serwer API próbował otworzyć połączenie TCP z węzłem na porcie 10250 i nie otrzymał odpowiedzi. i/o timeout oznacza, że pakiety zostały po cichu odrzucone, co sugeruje filtrowanie: przez lokalny firewall na węźle lub zewnętrzny firewall sieciowy dostawcy w panelu sterowania. connect: connection refused w tym samym miejscu oznacza sytuację odwrotną. Pakiet dotarł do celu, ale nikt go nie odebrał, co oznacza, że kubelet nie działa. Jest to ta sama para przyczyn opisana w connection refused versus connection timed out, omówiona tutaj w kontekście innego portu.

Węzły pozostają w stanie Ready przez cały ten czas, ponieważ status węzła jest przesyłany w drugą stronę. Kubelet łączy się wychodząco z serwerem API na porcie 6443 i wysyła własny sygnał kontrolny (heartbeat), co nie wymaga żadnego ruchu przychodzącego na port 10250. Zablokowany port 10250 powoduje zatem, że klaster normalnie planuje pody, a błędy występują tylko przy próbach pobrania logów, wykonania poleceń, przekierowania portów oraz odczytu metryk.

kubectl top node odpowiadające na error: Metrics API not available to ten sam błąd widziany z perspektywy metrics-server, którego logi wskazują konkretny węzeł oraz 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 timeout

Przetestuj ścieżkę przed edycją reguł zapory sieciowej

Uruchom poniższe polecenie z poziomu węzła płaszczyzny sterowania (control plane), kierując je na adres węzła roboczego (worker):

nc -zv 10.0.0.12 10250
curl -sk -o /dev/null -w '%{http_code}\n' https://10.0.0.12:10250/healthz

nc -z otwiera połączenie, zamyka je i wyświetla succeeded!, gdy port akceptuje żądanie. Polecenie curl jest lepszym testem, ponieważ potwierdza, że kubelet faktycznie obsługuje ruch, a nie tylko to, że port jest otwarty. Wyświetla ono 401. Jest to prawidłowy wynik: uzgadnianie TLS (transport layer security) zakończyło się pomyślnie, a następnie kubelet odrzucił nieuwierzytelnione żądanie, co jest zachowaniem oczekiwanym. -k pomija weryfikację certyfikatu, co jest dopuszczalne, ponieważ testowana jest ścieżka, a nie łańcuch zaufania.

Długa pauza kończąca się przekroczeniem czasu oczekiwania (timeout) oznacza, że pakiety są odrzucane. Wynik curl: (7) Failed to connect zwrócony natychmiastowo oznacza, że port jest zamknięty na osiągalnym hoście. Test należy przeprowadzić z węzła płaszczyzny sterowania, a nie z laptopa, ponieważ w tym przypadku istotny jest dostęp tylko z tej maszyny.

Wymagane porty dla płaszczyzny sterowania i węzła roboczego

Poniżej przedstawiono porty przychodzące wymienione w dokumentacji nadrzędnej. Na węźle płaszczyzny sterowania (control plane) należy otworzyć port TCP 6443 dla serwera API, dostępny dla wszystkich komponentów uruchamiających kubectl. Porty TCP od 2379 do 2380 służą do obsługi klienta etcd oraz API komunikacji między węzłami etcd; są one wykorzystywane przez serwer API oraz samą usługę etcd. Port TCP 10250 obsługuje API kubelet i jest używany przez sam węzeł oraz płaszczyznę sterowania. Porty TCP 10259 dla kube-scheduler oraz TCP 10257 dla kube-controller-manager są wykorzystywane wyłącznie przez sam węzeł.

Na węźle roboczym (worker node) należy otworzyć port TCP 10250 dla API kubelet, używany przez węzeł oraz płaszczyznę sterowania. Port TCP 10256 jest przeznaczony dla kube-proxy i jest używany przez sam węzeł oraz przez load balancery wykonujące testy sprawności (health checks). Porty TCP i UDP z zakresu od 30000 do 32767 służą dla usług typu NodePort; jest to domyślny zakres dostępny dla wszystkich klientów wymagających dostępu do tych usług.

Wtyczka CNI dodaje własne porty, które nie znajdują się na powyższej liście. Flannel oraz Calico w trybie VXLAN wymagają otwarcia portu UDP 4789 pomiędzy węzłami. Calico korzystające z BGP wymaga portu TCP 179. Należy sprawdzić dokumentację używanej wtyczki i otworzyć odpowiednie porty między węzłami, w przeciwnym razie komunikacja między podami na różnych węzłach nie będzie możliwa, nawet jeśli wszystkie porty wymienione w tej sekcji zostaną otwarte.

Otwarcie portu 10250 bez wystawiania go do Internetu

API kubelet pozwala na uruchomienie procesu wewnątrz dowolnego kontenera na danym węźle. Otwarty port 10250 należy traktować jak dostęp root do węzła i ograniczyć go na podstawie adresu źródłowego. Nigdy nie należy zezwalać na dostęp z dowolnego miejsca.

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 numbered

Zastąp 10.0.0.0/24 siecią, w której znajdują się Twoje węzły. Polecenie ufw status numbered wyświetla aktywne reguły wraz z indeksem, co pozwala usunąć błędną regułę za pomocą sudo ufw delete <number>. Podstawy ufw dla VPS omawiają kolejność reguł, która decyduje o tym, który z Twoich wpisów faktycznie zostanie zastosowany.

Jedno ustawienie ufw powoduje samodzielne zerwanie działania Kubernetes. Ruch podów przechodzący przez węzeł jest przekazywany (forwarded), a nie dostarczany lokalnie, podczas gdy ufw domyślnie odrzuca przekazywane pakiety. Ustaw DEFAULT_FORWARD_POLICY="ACCEPT" w pliku /etc/default/ufw i uruchom sudo ufw reload. Bez tego port 10250 może być w pełni otwarty, a komunikacja między podami na różnych węzłach i tak będzie kończyć się niepowodzeniem.

Sprawdź również zaporę sieciową dostawcy. Większość paneli VPS posiada zaporę sieciową na poziomie sieci, która znajduje się przed serwerem i jest niewidoczna dla ufw status. Reguła dodana na węźle nie przyniesie żadnego efektu, jeśli pakiet nigdy do niego nie dotrze.

Gdy port jest osiągalny, a żądanie nadal kończy się niepowodzeniem

Niektóre błędy na porcie 10250 zwracane są natychmiast, zamiast powodować zawieszenie połączenia. Oznacza to, że nawiązanie połączenia przebiegło pomyślnie, ale żądanie zostało odrzucone. Komunikat x509: certificate signed by unknown authority w dzienniku metrics-server oznacza, że kubelet używa certyfikatu z podpisem własnym, któremu scraper nie ufa. Standardowe rozwiązania to włączenie rotacji certyfikatów serwera kubelet, aby były one podpisywane przez CA klastra, a następnie zatwierdzenie żądania podpisania certyfikatu (CSR), lub – w przypadku klastrów laboratoryjnych – zaakceptowanie ryzyka i uruchomienie metrics-server z flagą --kubelet-insecure-tls.

Komunikat zawierający Forbidden wraz z nodes/proxy lub nodes/metrics wskazuje na błąd RBAC (role based access control). Klient uzyskał połączenie z kubeletem, kubelet zapytał serwer API, czy dana tożsamość ma uprawnienia do użycia podzasobu, a odpowiedź była odmowna. Należy poprawić obiekt ClusterRole przypisany do klienta. Zmiana konfiguracji firewalla nie pomoże, ponieważ żaden ruch nie został zablokowany.

Jeśli potrzebny jest tylko jeden mały klaster

Jeśli podczas pierwszego uruchamiania kubeadm na pojedynczym VPS występują te błędy, należy rozważyć, czy kubeadm jest w ogóle potrzebny. Jednowęzłowy klaster k3s na VPS zapewnia działające API Kubernetes za pomocą jednego polecenia, z już skonfigurowanymi komponentami kubelet, kube-proxy oraz CNI. Port 10250 nadal jest tam obecny i obowiązują dla niego te same zasady, jednak nie ma potrzeby samodzielnego zestawiania płaszczyzny sterowania (control plane).

FAQ

Do czego służy port 10250 w Kubernetes?

Jest to uwierzytelniony interfejs HTTPS usługi kubelet, działający na każdym węźle, zarówno w płaszczyźnie sterowania (control plane), jak i w węzłach roboczych (worker). Serwer API łączy się z nim w celu obsługi kubectl logs, kubectl exec, kubectl attach oraz kubectl port-forward, a metrics-server odpytuje go o /metrics/resource, aby dostarczyć kubectl top. Status węzła nie korzysta z tego portu, ponieważ kubelet wysyła swój sygnał kontrolny (heartbeat) wychodząco do serwera API na port 6443. Dlatego zablokowanie portu 10250 powoduje, że węzły wyświetlają Ready, podczas gdy pobieranie logów i wykonywanie poleceń kończy się niepowodzeniem.

Jak sprawdzić, co nasłuchuje na porcie 10250?

Uruchom sudo ss -lntp | grep 10250 na węźle. Pole users:((...)) na końcu linii wskazuje nazwę procesu oraz jego PID. sudo ma znaczenie, ponieważ bez uprawnień root kolumna z nazwą procesu pozostanie pusta. Jeśli właścicielem jest kubelet, sudo systemctl status kubelet --no-pager pozwoli ustalić, czy jest to poprawnie działający proces, czy usługa restartująca się w pętli. Jeśli właścicielem jest k3s, oznacza to, że na jednym serwerze zainstalowano dwie dystrybucje Kubernetes i jedną z nich należy usunąć.

Czy muszę otwierać port 10250 w zaporze sieciowej?

Tak, pomiędzy węzłami. Płaszczyzna sterowania musi mieć możliwość połączenia się z portem 10250 na każdym węźle, w tym na samym sobie; w przeciwnym razie logi, polecenia exec, port-forward oraz metryki przestaną działać. Ogranicz dostęp źródłowy do sieci, w której znajdują się węzły, na przykład sudo ufw allow from 10.0.0.0/24 to any port 10250 proto tcp. Nie otwieraj tego portu na świat: każdy, kto zdoła uwierzytelnić się na tym porcie, może uruchomić proces w dowolnym kontenerze na węźle.

Dlaczego kubectl logs nie działa tylko dla podów na jednym węźle?

Ponieważ blokada dotyczy konkretnego węzła, a serwer API łączy się z węzłem, na którym uruchomiony jest dany pod. Przeczytaj treść błędu: zawiera ona adres IP węzła, z którym próbowano nawiązać połączenie. Następnie uruchom nc -zv <node-ip> 10250 z poziomu węzła płaszczyzny sterowania. Przekroczenie czasu oczekiwania (timeout) wskazuje na zaporę sieciową na tym węźle lub na zaporę u dostawcy infrastruktury. connection refused wskazuje na to, że kubelet nie jest uruchomiony na danym węźle, więc sprawdź systemctl status kubelet bezpośrednio na tym węźle.