Fix 'The connection to the server localhost:8443 was refused' in Kubernetes

beginner☸️ Kubernetes2026-03-29| Kubernetes (any version), kubectl CLI, Linux/macOS/Windows, works with Minikube, kind, kubeadm clusters

Error Message

The connection to the server localhost:8443 was refused
#kubernetes#apiserver#kubectl#connection

What's happening

You run a kubectl command and get hit with:

The connection to the server localhost:8443 was refused - did you specify the right host or port?

kubectl is trying to reach the Kubernetes API server at localhost:8443 β€” but nothing is listening there. Three things cause this: the cluster isn't running, kubectl has no valid kubeconfig, or it's pointed at the wrong endpoint. Port 8443 is the Minikube default; kubeadm clusters use 6443. Seeing localhost:8443 on a kubeadm setup is a dead giveaway that your kubeconfig is stale or misconfigured.

Quick diagnosis

Narrow down the cause before touching anything. These four checks cover 95% of cases.

1. Check your current context

kubectl config current-context

An error here β€” or a context name you don't recognize β€” is often the whole problem. List everything configured:

kubectl config get-contexts

2. Check if kubeconfig exists

echo $KUBECONFIG
ls ~/.kube/config

No ~/.kube/config? That's your answer. When kubectl finds no config, it falls back to localhost:8443 β€” which is almost certainly wrong.

3. For local clusters (Minikube / kind)

# Minikube
minikube status

# kind
kind get clusters

A stopped or deleted cluster means kubectl has no API server to connect to.

4. For remote clusters (kubeadm / cloud)

kubectl cluster-info

Cross-check the server address in your kubeconfig against the real API server IP:

kubectl config view --minify | grep server

Fix by scenario

Scenario A: Local cluster is stopped (Minikube / kind)

Nine times out of ten, this is the culprit. Start it back up:

# Minikube
minikube start

# kind (recreate if deleted)
kind create cluster --name my-cluster

Minikube rewrites ~/.kube/config automatically on start. Once it's up, confirm everything looks good:

kubectl get nodes

Scenario B: No kubeconfig or empty config

Fresh machine? Config accidentally deleted? Regenerate it:

# Minikube β€” regenerates kubeconfig automatically
minikube update-context

# kubeadm β€” copy the admin config from the control plane node
scp user@control-plane-node:/etc/kubernetes/admin.conf ~/.kube/config
chmod 600 ~/.kube/config

The chmod 600 isn't optional. kubectl silently refuses to use a config file with world-readable permissions.

Cloud providers have their own one-liners:

# AWS EKS
aws eks update-kubeconfig --region us-east-1 --name my-cluster

# GKE
gcloud container clusters get-credentials my-cluster --zone us-central1-a

# AKS
az aks get-credentials --resource-group my-rg --name my-cluster

Scenario C: Wrong context selected

Switch to the right one:

kubectl config use-context my-correct-context

Don't want to change your default context permanently? The --context flag runs a one-off command against any cluster:

kubectl get pods --context=production-cluster

Scenario D: API server is down on a kubeadm cluster

SSH into the control plane and check whether the API server container is actually running:

sudo crictl ps | grep kube-apiserver

# Check kubelet logs for clues
sudo journalctl -u kubelet -n 100

# Confirm the static pod manifest is still there
ls /etc/kubernetes/manifests/kube-apiserver.yaml

If the pod crashed, pull its logs directly:

sudo crictl logs $(sudo crictl ps -a | grep kube-apiserver | awk '{print $1}')

Three things crash the API server most often: expired certificates, etcd going down, or a typo in the manifest flags. Fix the root cause β€” kubelet will restart the static pod on its own.

Scenario E: Firewall blocking the port

Server running but still unreachable from another machine? Test the connection before blaming the config:

# Test connectivity directly
telnet <api-server-ip> 6443
# or
curl -k https://<api-server-ip>:6443/healthz

Open the port if it's blocked:

# UFW (Ubuntu)
sudo ufw allow 6443/tcp

# firewalld (RHEL/CentOS)
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --reload

Worth repeating: kubeadm uses 6443 by default, not 8443. If you're hitting localhost:8443 on a kubeadm cluster, the problem is the kubeconfig server URL β€” not the firewall.

Scenario F: Stale server URL in kubeconfig

API server moved to a new IP after a rebuild? Update the URL directly in your kubeconfig:

# Update the server URL
kubectl config set-cluster my-cluster --server=https://<new-api-server-ip>:6443

# Confirm the change took effect
kubectl config view --minify | grep server

Verify the fix

kubectl cluster-info
kubectl get nodes
kubectl get pods -A

A healthy cluster returns something like this from kubectl cluster-info:

Kubernetes control plane is running at https://<server>:<port>
CoreDNS is running at https://<server>:<port>/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

Prevent it going forward

  • Minikube users: add minikube start to your dev environment startup script. A 30-second startup beats hunting down this error mid-session.
  • kubeadm clusters: put kube-apiserver under Prometheus + Alertmanager monitoring. Get paged before your developers notice kubectl is broken.
  • Remote clusters: treat kubeconfig like a password β€” store it in a secrets manager, and bake aws eks update-kubeconfig or gcloud get-credentials into your onboarding scripts so credentials never expire silently.
  • Multiple clusters: install kubectx. Switching contexts with kubectx production instead of the full kubectl config use-context command takes two seconds and removes a whole class of "why is nothing working" moments.

Related Error Notes