Service not routing traffic — no endpoints
curl to Service IP returns connection refused
Focused incident mode — strips away everything but this runbook.
Symptoms
- curl to Service IP returns connection refused
- kubectl get endpoints shows <none>
- App runs but gets no traffic
A Service only forwards to pods whose labels satisfy its selector AND are Ready. Empty endpoints almost always = selector typo or NotReady pods.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Endpoints list
kubectl get endpoints <svc> -n <namespace>Service selector
kubectl describe svc <svc> -n <namespace> | grep Selector
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Endpoints are empty while pods exist
- describe Selector differs from pod labels by one key/value
Confirm before fixing
kubectl get ep <svc> -n <namespace>Empty ENDPOINTS column confirms the mismatch
Fix
kubectl patch svc <svc> -n <namespace> --type merge -p '{"spec":{"selector":{"app":"<app>"}}}'Correct the selector
Expected: service/<svc> patched
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
kubectl get endpoints <svc> -n <namespace>Confirm empty endpoints
kubectl describe svc <svc> -n <namespace> | grep SelectorRead the selector
kubectl get pods -n <namespace> --show-labels | grep <app>Compare with actual pod labels
kubectl get pods -n <namespace> -l <selector>Verify Ready state of matched pods
Prevention
- Add a post-deploy check: kubectl get ep <svc> is non-empty.
- Use kubectl get endpoints as a readiness gate in CI.
- Prefer 'kubectl expose' or kustomize to generate selectors that always match.
Related runbooks
Same stack, same failure family — worth a skim.
kubectl rollout status hangs on 'Waiting for rollout to finish'
kubectl get pods shows CrashLoopBackOff status
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.