Kubernetes Ingress 503 Service Unavailable: 5 Causes and Fixes
Nginx Ingress returning 503 Service Unavailable? These 5 fixes cover no healthy backends, wrong service name, port mismatch, readiness probe failures, and connection refused — with exact kubectl commands.
503 from Kubernetes Ingress means the Ingress controller cannot reach healthy backend pods. Here are the five causes, from most to least common.
Quick Diagnosis
# Check if pods are running
kubectl get pods -n <namespace> -l app=<your-app>
# Check the Ingress
kubectl describe ingress <name> -n <namespace>
# Check nginx ingress controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=50 | grep 503
# Check if the service has endpoints
kubectl get endpoints <service-name> -n <namespace>
# If ENDPOINTS shows "none" — that is your problemCause 1: No Healthy Pod Endpoints
The most common cause. The Service exists but has no healthy pods behind it.
Check:
kubectl get endpoints myapp-service -n production
# NAME ENDPOINTS AGE
# myapp-service <none> 5m ← Problem!Why endpoints can be empty:
- All pods are in Pending, CrashLoopBackOff, or Terminating
- Pods exist but readiness probe is failing (pods are Running but not Ready)
- Label selector in Service does not match pod labels
Fix — check pod labels vs service selector:
# Service selector
kubectl get svc myapp-service -n production -o jsonpath='{.spec.selector}'
# {"app":"myapp","version":"v1"}
# Pod labels
kubectl get pod myapp-xyz -n production -o jsonpath='{.metadata.labels}'
# {"app":"myapp","version":"v2"} ← Mismatch! version label differsFix the label mismatch in either the Service or the Deployment.
Cause 2: Wrong Service Name or Port in Ingress
# Broken Ingress
spec:
rules:
- host: myapp.example.com
http:
paths:
- backend:
service:
name: myapp-svc # Wrong — service is named 'myapp-service'
port:
number: 8080 # Wrong — service port is 80Check:
kubectl get svc -n production | grep myapp
# myapp-service ClusterIP 10.0.0.1 <none> 80/TCP
kubectl describe ingress myapp-ingress -n production | grep -A 10 "Rules:"
# Shows what the Ingress is targetingFix:
spec:
rules:
- host: myapp.example.com
http:
paths:
- backend:
service:
name: myapp-service # Exact service name
port:
number: 80 # Service port, not container portThe port.number is the Service port (in spec.ports[].port), not the container port.
Cause 3: Readiness Probe Failing
Pods show as Running but are not Ready. Ingress only routes to Ready pods.
kubectl get pods -n production
# NAME READY STATUS RESTARTS
# myapp-xyz-abc 0/1 Running 0 ← 0/1 = not ready
# Check why
kubectl describe pod myapp-xyz-abc -n production | grep -A 15 "Readiness:"
# Shows readiness probe config and failure reasonCommon readiness probe fixes:
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30 # Give app time to start
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5 # Increase if app is slow to respondTest manually:
kubectl exec -it myapp-xyz-abc -n production -- curl -s localhost:8080/health
# If this fails or hangs — that is your readiness probe failureCause 4: Ingress Class Missing or Wrong
In newer Kubernetes versions (1.18+), you must specify the ingress class.
kubectl get ingressclass
# NAME CONTROLLER PARAMETERS AGE
# nginx k8s.io/ingress-nginx <none> 10d# Add annotation or ingressClassName
metadata:
annotations:
kubernetes.io/ingress.class: nginx # Older syntax
# OR (newer syntax)
spec:
ingressClassName: nginxCause 5: NetworkPolicy Blocking Traffic
If you have NetworkPolicy enabled, Ingress traffic may be blocked.
kubectl get networkpolicy -n productionAllow Ingress controller to reach your pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: 8080Full Fix Checklist
# 1. Check pod health
kubectl get pods -n production -l app=myapp
# Look for READY: 1/1 and STATUS: Running
# 2. Check endpoints
kubectl get endpoints myapp-service -n production
# Should show IP addresses, not <none>
# 3. Check service selector matches pod labels
kubectl get svc myapp-service -n production -o yaml | grep -A 5 selector
kubectl get pods -n production -l app=myapp --show-labels
# 4. Test direct access to pod (bypass Ingress)
kubectl port-forward pod/myapp-xyz -n production 8080:8080
curl localhost:8080/health
# If this works, problem is between Ingress and Service
# 5. Test via Service (bypass Ingress)
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
curl myapp-service.production.svc.cluster.local/health
# If this works, problem is in the Ingress config
# 6. Check Ingress controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100 | grep -i error503 means no healthy backends. Start at the pod level (is it Ready?) and work up to the Service (does it have endpoints?) then the Ingress config (correct name and port?).
More Ingress fixes? Read our Nginx Ingress 502 bad gateway fix and Kubernetes service not routing traffic fix.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
AWS RDS Connection Timeout from EKS Pods — How to Fix It
EKS pods can't connect to RDS? Fix RDS connection timeouts from Kubernetes — covers security groups, VPC peering, subnet routing, and IAM auth issues.
Ingress-NGINX Is Being Retired: How to Migrate to Gateway API Before It Breaks
Ingress-NGINX is officially being retired. Your ingress rules will stop working. Here's the step-by-step migration plan to Kubernetes Gateway API before it's too late.
Kubernetes DNS Not Working: How to Fix CoreDNS Failures in Production
Pods can't resolve hostnames? Getting NXDOMAIN or 'no such host' errors? Here's how to diagnose and fix CoreDNS issues in Kubernetes step by step.