SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-21

Sửa lỗi kubelet port 10250 trên Ubuntu

Cổng 10250 là kubelet API. Sửa lỗi “address already in use” khi kubeadm init và firewall drop khiến kubectl logs, exec thất bại trên node.

Cổng 10250 là gì

Cổng 10250 là kubelet API. Mọi lỗi nhắc đến cổng này đều thuộc một trong hai nhóm đối lập. Hoặc đã có tiến trình khác chiếm cổng, nên kubeadm init không thể chạy. Hoặc không có gì truy cập được cổng, nên kubectl logskubectl exec thất bại khi làm việc với một node vốn vẫn hoạt động bình thường.

kubelet là agent mà Kubernetes chạy trên mọi node. Nó khởi động container và báo trạng thái của chúng về control plane. kubelet cũng lắng nghe trên TCP 10250 và cung cấp một HTTPS API để control plane gọi đến. API server mở kết nối đến cổng này khi bạn chạy kubectl logs, kubectl exec, kubectl attach hoặc kubectl port-forward. metrics-server thu thập dữ liệu từ /metrics/resource trên cùng cổng, nhờ đó kubectl top node hoạt động.

API này yêu cầu xác thực. kubeadm tắt quyền truy cập ẩn danh và cấu hình kubelet sử dụng cluster CA (certificate authority). Vì vậy, request không có credential sẽ nhận Unauthorized thay vì có shell bên trong một container của bạn. Hãy nhớ chi tiết này, vì đây cũng là cách nhanh nhất để xác nhận cổng có thể truy cập được. Nếu bạn chưa quen với port, port thực sự là gì trên Linux giải thích mô hình được dùng trong hướng dẫn này.

Cả hai kiểu lỗi đều xuất phát từ cùng một yêu cầu. Cổng 10250 phải còn trống trước khi kubelet khởi động và phải có thể truy cập từ control plane sau khi kubelet chạy.

Bạn gặp vấn đề nào trong hai vấn đề này

Chạy các lệnh sau trên node gặp vấn đề. Bạn tự chạy từng lệnh trên server của mình.

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

ss -lntp liệt kê các socket TCP đang listen cùng với process tương ứng. -l nghĩa là đang listen, -n giữ nguyên port ở dạng số, -t giới hạn kết quả ở TCP, còn -p hiển thị process đang sở hữu socket. Flag cuối cần quyền root. Nếu không, cột process sẽ trống và bạn không thu được thông tin nào.

Dòng kết thúc bằng users:(("kubelet",pid=1043,fd=23)) nghĩa là kubelet đang chạy và đang giữ port. Nếu bạn nghĩ port này phải được giải phóng, thì đây chính là nguyên nhân. Nếu ss không in ra gì và control plane vẫn không thể kết nối đến node này, thì firewall chưa liên quan, vì hiện không có process nào phục vụ trên port đó. Hãy tìm nguyên nhân kubelet không chạy trước khi thay đổi rule.

systemctl status kubelet cung cấp nửa thông tin còn lại. active (running) với thời gian bắt đầu từ vài phút trước là bình thường. Kubelet restart vài giây một lần trước khi bạn chạy kubeadm init hoặc kubeadm join cũng là bình thường: unit được đóng gói khởi động ngay khi cài đặt, không tìm thấy config rồi thoát. Tài liệu upstream mô tả crash loop này là hành vi dự kiến trong khi kubelet chờ kubeadm cho biết cần thực hiện gì. Nếu bạn chưa quen với hành vi restart của systemd, hãy xem cách systemd service type và restart policy hoạt động để biết bối cảnh của phần này.

Vì sao cổng 10250 đã được sử dụng khi chạy kubeadm init

kubeadm init thực hiện các preflight check trước khi ghi bất kỳ dữ liệu nào vào disk. Một trong các bước kiểm tra này thử bind từng cổng mà control plane cần. Nếu bind thất bại, bước kiểm tra dừng và báo lỗi chỉ rõ cổng 10250. Đây không phải bug. kubeadm từ chối dựng cluster thứ hai trên phần còn lại của cluster thứ nhất.

Trong thực tế, có 4 nguyên nhân:

  • Một lần chạy kubeadm init hoặc kubeadm join trước đó bị fail giữa chừng. kubelet đã nhận được config, nên đang chạy và giữ cổng này.
  • Một kubeadm reset đã được start nhưng chưa hoàn tất. Reset sẽ stop kubelet nhưng không disable unit. Vì vậy, lần reboot tiếp theo sẽ khởi động lại listener.
  • k3s hoặc một Kubernetes distribution khác đã được cài trên cùng server. k3s tích hợp kubelet, và kubelet đó cũng bind cổng 10250.
  • Package kubelet được apt cài thêm và khởi động bằng systemd unit riêng, trên một máy chưa từng chạy kubeadm.

Hãy xác định nguyên nhân trước khi thay đổi bất kỳ thứ gì:

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

Nếu listener thuộc về k3s, hãy stop nó và xác định cluster nào bạn thực sự muốn sử dụng. k3s và kubeadm không thể dùng chung một server vì chúng chiếm cùng các cổng và cùng thư mục CNI (container network interface). Trên server node, trình cài đặt k3s để lại script gỡ cài đặt tại /usr/local/bin/k3s-uninstall.sh; trên agent node, script nằm tại k3s-agent-uninstall.sh.

Vì sao kill kubelet không giải phóng cổng

sudo pkill kubelet giải phóng cổng 10250 trong khoảng 10 giây. Unit do package cung cấp đặt chính sách restart, nên systemd khởi động một kubelet mới và kubelet này bind lại cùng cổng. Bạn có thể tự kiểm tra chính sách này:

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

Restart=always cùng với RestartSec=10 là cấu hình mặc định của unit. Đây chính là lý do kill trông như đã hoạt động, nhưng sau đó lại không còn tác dụng. systemctl stop là cách đúng để giải phóng cổng, vì systemd sẽ không tiếp tục restart một unit mà bạn đã yêu cầu stop.

Một cổng đã được giải phóng vẫn chưa đủ trên một node đang chứa một phần lớn của cluster. /var/lib/kubelet/config.yaml, các certificate trong /etc/kubernetes/pki và mọi static pod manifest trong /etc/kubernetes/manifests vẫn còn đó. Các preflight check về sau sẽ gặp vấn đề với những file này. Nếu buộc bỏ qua các check, bạn sẽ có một cluster mà certificate không khớp với config. Hãy reset node đúng cách.

Đặt lại node sạch sẽ

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 bỏ qua prompt xác nhận. Lệnh reset cố gắng hoàn tác những thay đổi do init hoặc join thực hiện. Lệnh này xóa các file và cấu hình cục bộ, xóa member etcd cục bộ trên control plane node, xóa các certificate trong /etc/kubernetes/pki, đồng thời xóa cấu hình và manifest của kubelet.

Tài liệu nêu rõ những gì reset để lại, và từng mục đều có thể gây lỗi nếu không để ý. Lệnh này không xóa /etc/cni/net.d, nên cấu hình CNI plugin cũ vẫn còn và cluster mới sẽ đọc cấu hình đó. Lệnh này không xóa các rule của iptables, nftables hoặc IPVS mà kube-proxy đã áp dụng lên host. Lệnh này cũng không tác động đến $HOME/.kube, nên kubectl vẫn cố kết nối đến cluster không còn tồn tại và trả về các lỗi certificate, khiến bạn tưởng đó là một vấn đề mới.

Các rule xử lý packet còn sót lại là phần khó xử lý nhất. Nếu tự flush các table, bạn cũng xóa các rule do ufw cài đặt, vì ufw trên Ubuntu ghi rule thông qua cùng backend. Khi đó server không còn được lọc traffic cho đến khi bạn chạy sudo ufw reload. Với node mà bạn ohnehin sẽ rebuild, hãy reboot sau khi reset. Reboot sẽ xóa các rule runtime do kube-proxy thêm vào và tốn ít thời gian hơn việc gỡ một ruleset đã bị flush dở dang. Vì sao rule iptables và rule nftables xuất hiện trong output của nhau giải thích cơ chế bên dưới.

Lệnh ss cuối cùng phải không in ra gì. Không có listener trên 10250, 6443 hoặc 2379 nghĩa là node đã sẵn sàng cho một kubeadm init mới.

Vì sao kubectl logs và kubectl exec bị timeout trên cổng 10250

Đây là lỗi ngược lại và không biểu hiện rõ là vấn đề về cổng. Cluster vẫn khởi động. Các node vẫn ở trạng thái Ready. Pod vẫn chạy. Sau đó một lệnh bị lỗi:

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

Đọc thông báo đó từ cuối lên. API server đã cố mở kết nối TCP đến node trên cổng 10250 nhưng không nhận được phản hồi. i/o timeout có nghĩa là các packet bị âm thầm drop, nên có thành phần đang lọc chúng: firewall trên node hoặc network firewall riêng của nhà cung cấp trong control panel. connect: connection refused ở cùng vị trí có nghĩa ngược lại. Packet đã đến nơi nhưng không có tiến trình nào listening, nên kubelet đang dừng. Đây là cùng một cặp nguyên nhân được mô tả trong connection refused và connection timed out, nhưng xảy ra trên một cổng khác.

Node vẫn ở trạng thái Ready trong suốt thời gian này vì trạng thái node truyền theo chiều ngược lại. Kubelet kết nối ra ngoài đến API server trên cổng 6443 và gửi heartbeat của chính nó. Việc này không cần kết nối inbound trên cổng 10250. Vì vậy, khi 10250 bị chặn, cluster vẫn schedule pod bình thường nhưng chỉ lỗi với logs, exec, port-forward và metrics.

kubectl top node trả về error: Metrics API not available là cùng một lỗi được nhìn qua metrics-server. Log của metrics-server ghi rõ node và cổng:

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

Kiểm tra đường đi trước khi chỉnh sửa bất kỳ firewall rule nào

Chạy lệnh này từ một control plane node, đến địa chỉ của 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 mở kết nối, đóng kết nối rồi in succeeded! khi port chấp nhận kết nối. Dòng curl là phép kiểm tra tốt hơn vì nó xác nhận kubelet đang phục vụ, thay vì chỉ xác nhận port đang mở. Lệnh này in 401. Đây là kết quả bình thường: quá trình bắt tay TLS (transport layer security) đã hoàn tất, sau đó kubelet từ chối request chưa được xác thực, đúng như thiết kế. -k bỏ qua bước kiểm tra certificate. Điều này phù hợp vì bạn đang kiểm tra đường đi, không kiểm tra trust chain.

Thời gian chờ lâu rồi kết thúc bằng timeout nghĩa là các packet đang bị drop. curl: (7) Failed to connect trả về ngay lập tức nghĩa là port đang đóng trên một host có thể truy cập. Hãy kiểm tra từ control plane node, không phải từ laptop của bạn, vì control plane là máy duy nhất cần truy cập được trong trường hợp này.

Các cổng mà control plane và worker cần

Đây là các cổng inbound được upstream liệt kê. Trên node control plane, cần TCP 6443 cho API server và mở cho mọi thành phần chạy kubectl. Cần TCP 2379 đến 2380 cho client API và peer API của etcd; API server và chính etcd sử dụng các cổng này. Cần TCP 10250 cho kubelet API; node và control plane sử dụng cổng này. TCP 10259 cho kube-scheduler và TCP 10257 cho kube-controller-manager chỉ được chính node đó sử dụng.

Trên node worker, cần TCP 10250 cho kubelet API; node và control plane sử dụng cổng này. Cần TCP 10256 cho kube-proxy; node và các load balancer thực hiện health check sử dụng cổng này. Cần TCP và UDP từ 30000 đến 32767 cho các service NodePort. Đây là dải mặc định và có thể được truy cập bởi các thành phần cần dùng những service đó.

CNI plugin của bạn sẽ thêm các cổng riêng ngoài danh sách này, nhưng các cổng đó không được liệt kê ở đây. Flannel và Calico ở chế độ VXLAN cần UDP 4789 giữa các node. Calico dùng BGP cần TCP 179. Hãy kiểm tra tài liệu của plugin và mở các cổng đó giữa các node. Nếu không, các pod trên những node khác nhau sẽ không thể giao tiếp với nhau dù mọi cổng trong phần này đều đã mở.

Mở cổng 10250 mà không expose cổng này ra Internet

Kubelet API có thể khởi động một process bên trong bất kỳ container nào trên node đó. Hãy coi cổng 10250 đang mở tương đương với quyền root trên node và giới hạn theo địa chỉ nguồn. Không bao giờ cho phép truy cập từ mọi địa chỉ.

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

Thay 10.0.0.0/24 bằng network dùng chung giữa các node. ufw status numbered liệt kê các rule đang hoạt động kèm index, nên bạn có thể xóa rule sai bằng sudo ufw delete <number>. Tổng quan về ufw cho VPS giải thích thứ tự rule, yếu tố quyết định entry nào thực sự được áp dụng.

Một setting của ufw có thể tự làm Kubernetes bị lỗi. Traffic của pod đi qua node là traffic được forward, không phải traffic được gửi đến máy cục bộ, và ufw mặc định drop các packet được forward. Đặt DEFAULT_FORWARD_POLICY="ACCEPT" trong /etc/default/ufw rồi chạy sudo ufw reload. Nếu không làm vậy, cổng 10250 có thể mở hoàn toàn nhưng traffic giữa các pod trên các node vẫn bị lỗi.

Đồng thời kiểm tra firewall của nhà cung cấp. Hầu hết panel VPS có firewall ở cấp network, nằm phía trước server và không hiển thị trong ufw status. Rule bạn thêm trên node sẽ không có tác dụng nếu packet không đến được server.

Khi có thể truy cập cổng nhưng request vẫn thất bại

Một số lỗi 10250 trả về ngay lập tức thay vì treo, cho thấy kết nối đã thành công nhưng request bị từ chối. x509: certificate signed by unknown authority trong log của metrics-server có nghĩa là kubelet đang cung cấp self-signed certificate mà scraper không tin cậy. Cách xử lý thường là bật tính năng xoay vòng serving certificate của kubelet để cluster CA ký certificate đó, sau đó phê duyệt certificate signing request; hoặc chấp nhận rủi ro trên cluster lab và chạy metrics-server với --kubelet-insecure-tls.

Thông báo chứa Forbidden cùng với nodes/proxy hoặc nodes/metrics là lỗi RBAC (role-based access control). Caller đã kết nối được đến kubelet, kubelet hỏi API server xem identity đó có được phép dùng subresource hay không, và câu trả lời là không. Hãy sửa ClusterRole của caller. Không thay đổi firewall sẽ giúp ích, vì không có gì bị chặn.

Nếu bạn chỉ cần một cluster nhỏ

Nếu gặp các lỗi này khi lần đầu thiết lập kubeadm trên một VPS duy nhất, hãy cân nhắc xem bạn có thực sự cần kubeadm không. Một cluster k3s một node trên VPS cung cấp Kubernetes API hoạt động được chỉ bằng một lệnh, với kubelet, kube-proxy và một CNI đã được cấu hình sẵn để phối hợp với nhau. Cổng 10250 vẫn tồn tại trong mô hình đó và các quy tắc tương tự vẫn áp dụng cho cổng này, nhưng bạn không còn phải tự lắp ráp control plane.

FAQ

Cổng 10250 trong Kubernetes được dùng để làm gì?

Đây là API HTTPS có xác thực của kubelet trên mọi node, bao gồm cả control plane và worker. API server kết nối đến cổng này để thực hiện kubectl logs, kubectl exec, kubectl attachkubectl port-forward. metrics-server scrape /metrics/resource trên cổng này để cung cấp kubectl top. Trạng thái node không dùng cổng này vì kubelet gửi heartbeat outbound đến API server trên cổng 6443. Vì vậy, khi 10250 bị chặn, node hiển thị Ready nhưng log và exec đều fail.

Làm cách nào để biết tiến trình nào đang listen trên cổng 10250?

Chạy sudo ss -lntp | grep 10250 trên node. Trường users:((...)) ở cuối dòng cho biết tên process và PID của process đó. sudo rất quan trọng vì nếu không có quyền root thì cột process sẽ để trống. Nếu process sở hữu là kubelet, sudo systemctl status kubelet --no-pager cho biết kubelet đang hoạt động bình thường hay restart liên tục. Nếu process sở hữu là k3s, bạn đã cài 2 bản phân phối Kubernetes trên cùng một server và cần gỡ bỏ một bản.

Tôi có phải mở cổng 10250 trên firewall không?

Có, giữa các node. Control plane phải kết nối được đến cổng 10250 trên mọi node, kể cả chính nó. Nếu không, log, exec, port-forward và metrics đều fail. Hãy giới hạn source ở network dùng chung giữa các node, ví dụ sudo ufw allow from 10.0.0.0/24 to any port 10250 proto tcp. Không mở cổng này ra internet. Bất kỳ client nào có thể authenticate với cổng đó đều có thể chạy process trong bất kỳ container nào trên node.

Tại sao kubectl logs chỉ fail với pod trên một node?

Vì rule chặn áp dụng theo từng node, còn API server kết nối đến đúng node đang host pod đó. Đọc nội dung lỗi. Lỗi sẽ chứa địa chỉ IP của node mà API server đã cố kết nối. Sau đó chạy nc -zv <node-ip> 10250 từ một control plane node. Timeout thường cho thấy firewall trên node đó hoặc network firewall của provider đang chặn kết nối. connection refused cho thấy kubelet trên node đó không chạy, vì vậy hãy kiểm tra systemctl status kubelet trực tiếp trên node đó.