kubeadm join fails with http//localhost10248/healthz connection refused
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When kubeadm join fails with http://localhost:10248/healthz connection refused, it means the kubelet is not running or not listening on port 10248. The most common cause is that the container runtime (Docker or containerd) is not running, or the kubelet service failed to start due to a swap-enabled system, cgroup driver mismatch, or missing configuration. Fix it by checking systemctl status kubelet, reading the kubelet logs, and resolving the underlying issue.
The Error
Port 10248 is the kubelet healthz endpoint. If the kubelet is not running, nothing responds on that port.
Step 1: Check Kubelet Status
Common log messages and their fixes:
| Log Message | Cause | Fix |
failed to run Kubelet: running with swap on is not supported | Swap is enabled | swapoff -a |
failed to create kubelet: misconfiguration: kubelet cgroup driver | cgroup mismatch | Match kubelet and container runtime cgroup drivers |
Unable to connect to the server | API server unreachable | Check control plane status |
Step 2: Disable Swap
Kubernetes requires swap to be disabled:
Step 3: Ensure Container Runtime Is Running
Step 4: Fix cgroup Driver Mismatch
The kubelet and the container runtime must use the same cgroup driver (either cgroupfs or systemd):
If they do not match, update the kubelet configuration:
Then restart kubelet:
Step 5: Reset and Rejoin
If the node was previously joined and you need to start fresh:
Step 6: Generate a New Token If Expired
Tokens expire after 24 hours by default:
Firewall and Port Requirements
Ensure these ports are open on the worker node:
Common Pitfalls
- Running
kubeadm joinwithout disabling swap first: Kubernetes does not support swap by default. The kubelet refuses to start if swap is active. Always runswapoff -abefore joining and comment out swap entries in/etc/fstabfor persistence. - Mismatched cgroup drivers between kubelet and container runtime: If the container runtime uses
systemdand kubelet usescgroupfs(or vice versa), the kubelet crashes on startup. Both must use the same driver —systemdis recommended for modern distributions. - Not running
kubeadm resetbefore retrying a failed join: A failedkubeadm joinleaves partial state in/etc/kubernetes/. Retrying withoutkubeadm resetcauses preflight errors about existing files. Always reset before retrying. - Using an expired join token: Tokens from
kubeadm token createexpire after 24 hours. If the join command was generated earlier, generate a new token withkubeadm token create --print-join-command. - Forgetting to load required kernel modules: Kubernetes networking requires
br_netfilterandoverlaymodules. Runmodprobe br_netfilter overlayand add them to/etc/modules-load.d/k8s.conffor persistence. Without them, pod networking fails after the node joins.
Summary
connection refusedon port 10248 means the kubelet is not running — check withsystemctl status kubelet- Disable swap with
swapoff -aand remove swap entries from/etc/fstab - Ensure the container runtime (containerd/Docker/CRI-O) is running and enabled
- Match the cgroup driver between kubelet and the container runtime (use
systemd) - Run
kubeadm resetbefore retrying a failed join, and generate a fresh token if needed

