kubectl "connection refused" troubleshooting
Troubleshoots kubectl connection refused errors. Use when every kubectl command fails to reach the API server, after context switches, or when a local proxy dies. Covers kubeconfig server address, context selection, and proxy env vars. Not for Unauthorized/Forbidden errors, TLS cert problems, or in-cluster service networking.
TL;DR
kubectl reporting "connection refused" means the CLI cannot reach the Kubernetes API server at all. The usual causes are a wrong or stale kubeconfig context, the cluster being down or unreachable from your network, or a local proxy/port-forward that died. Verify the configured server address first, then check whether anything is actually listening there.
Error / query
kubectl "connection refused" troubleshootingUse this skill when
- Every
kubectlcommand fails withThe connection to the server [host]:[port] was refused kubectl cluster-infofails but other network tools work- A previously working kubeconfig suddenly stops connecting
- You just switched contexts and commands stopped working
Not for this skill when
- The error is
UnauthorizedorForbidden(auth/RBAC problem, the connection itself works) - The error mentions TLS certificates (expired or untrusted certs, not refused connections)
- Only one namespace or resource type fails (permissions, not connectivity)
- You are debugging pod-to-service traffic inside the cluster (that is service networking, not kubectl)
Steps
Step 1: See which server kubectl is trying to reach
kubectl config view --minifyExpected: the server: address and current context. If the address points at the wrong cluster, a dead port-forward, or YOUR_THE_HOST loopback address:[port] from a stopped proxy, you have found it.
Step 2: Confirm the current context is the one you want
kubectl config get-contextsExpected: a list of contexts with the current one starred. If the wrong context is active, switch with kubectl config use-context [name] and retry.
Step 3: Test raw TCP connectivity to the API server
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
echo "$APISERVER"
curl -sk --max-time 5 "$APISERVER/healthz"Expected: if curl also fails to connect, the problem is network reachability (cluster down, firewall, VPN off). If curl connects but kubectl does not, suspect the kubeconfig (proxy settings, cert paths).
Step 4: Check for a dead local proxy or expired credentials file
ls -la ~/.kube/config
env | grep -i -E "proxy|kube"Expected: the kubeconfig exists and is readable, and no stale HTTPS_PROXY is redirecting cluster traffic. A proxy env var set for office traffic is a classic cause of refused connections to internal clusters.
Step 5: Re-authenticate or regenerate the kubeconfig
kubectl config use-context [correct-context]
kubectl cluster-infoExpected: Kubernetes control plane is running at [address]. If it still fails, regenerate the kubeconfig from your cluster provider (cloud console, az aks get-credentials, aws eks update-kubeconfig, etc.) and retry.
Variant phrasings
"kubectl cannot connect to server"
Same thing. Start with step 1; the configured server address is wrong or unreachable in most cases.
"the connection to the server was refused did you specify the right host or port"
This is the full kubectl error text. It almost always means the kubeconfig points at a dead address, check context and server first.
"kubectl works on VPN but not off it"
The API server is on a private network. Either connect the VPN or expose the API through an authorized network, per your cluster's access policy.
Why it happens
kubectl is just an HTTPS client; "connection refused" happens at the TCP layer before any Kubernetes logic runs. Either nothing is listening at that address (wrong host/port, cluster down, dead port-forward) or something in the middle (firewall, missing VPN, bad proxy env) blocks the SYN. The kubeconfig is a local file, so a stale or switched context is the most common root cause.
Edge cases and pitfalls
- Kind/minikube clusters die when the VM stops;
minikube statusor the docker daemon state tells you fast. - Multiple kubeconfig files merge via
KUBECONFIG; a stale entry in a second file can shadow the right one. - Some corporate proxies intercept and refuse non-proxied HTTPS; add the cluster IP to
NO_PROXY. - Port-forwards (
kubectl proxy, ssh tunnels) die silently; the refused connection is on your machine, not the cluster. - After a cluster upgrade the API server address or CA can change; regenerate credentials rather than editing the file by hand.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_v9OaRFdSqIg0PMmGDe8OTw