1. Introduction

A Kubernetes Ingress resource that isn't routing traffic is one of those failures that can stem from any of five completely different root causes — and the error message is usually just a timeout or connection refused, with no indication of which layer broke. You might have deployed the Ingress resource correctly but the controller isn't watching it, or the controller is running but the Service it's targeting has no ready endpoints, or TLS is misconfigured and HTTPS is silently failing.

This guide covers the complete diagnostic path: verifying the Ingress controller is running, confirming the Ingress has an address, checking backend Service and pod health, and debugging TLS and annotation issues.

2. What "Ingress Not Working" Can Mean

In Kubernetes, an Ingress resource is just a configuration object — it doesn't route traffic by itself. An Ingress controller (NGINX Ingress Controller, AWS Load Balancer Controller, Traefik, etc.) reads Ingress objects and configures an actual load balancer or proxy. If the controller isn't running, isn't watching the right class, or has misconfigured permissions, the Ingress resource exists in Kubernetes but has no effect.

3. Common Causes

4. Step-by-Step Diagnosis and Fix

Step 1: Confirm the Ingress has an address

# Check if the Ingress has been assigned an address
kubectl get ingress -n <namespace>

# Output should show an ADDRESS — if empty, the controller hasn't provisioned it
# NAME         CLASS   HOSTS            ADDRESS          PORTS   AGE
# my-ingress   nginx   app.example.com  203.0.113.1      80,443  5m

# If ADDRESS is empty:
kubectl describe ingress my-ingress -n <namespace>
# Look at Events section for controller error messages

Step 2: Check the Ingress controller is running

# For NGINX Ingress Controller
kubectl get pods -n ingress-nginx
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller --tail=50

# For AWS Load Balancer Controller
kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller
kubectl logs -n kube-system deployment/aws-load-balancer-controller --tail=50

# For Traefik
kubectl get pods -n traefik
kubectl logs -n traefik deployment/traefik --tail=50

Step 3: Verify the Ingress class annotation

# View current Ingress spec
kubectl get ingress my-ingress -n <namespace> -o yaml

# Kubernetes 1.18+: use spec.ingressClassName
spec:
  ingressClassName: nginx   # must match the IngressClass resource name

# Or use the annotation (older approach, still works)
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx

# List available IngressClass resources in the cluster
kubectl get ingressclass

# NAME    CONTROLLER             PARAMETERS   AGE
# nginx   k8s.io/ingress-nginx   <none>       10d

Step 4: Verify the backend Service exists and has endpoints

# Check the Service referenced in the Ingress
kubectl get service my-service -n <namespace>

# Check that the Service has endpoints (pods are ready)
kubectl get endpoints my-service -n <namespace>

# If ENDPOINTS is <none> — the Service selector doesn't match any running pods
kubectl describe endpoints my-service -n <namespace>

# Verify the pod selector matches
kubectl get pods -n <namespace> -l app=my-app  # use your actual label selector
# All pods should be Running 1/1

Step 5: Test connectivity to the backend Service directly

# Bypass the Ingress and test the Service directly using a debug pod
kubectl run debug --image=curlimages/curl --rm -it --restart=Never --   curl -s http://my-service.<namespace>.svc.cluster.local:<port>/health

# Or test via port-forward to the Service
kubectl port-forward service/my-service -n <namespace> 8080:80 &
curl http://localhost:8080/health

# Expected: 200 response from your application
# If this fails, the problem is in the backend, not the Ingress

Step 6: Check TLS configuration

# Verify the TLS secret exists in the correct namespace
kubectl get secret my-tls-secret -n <namespace>

# Check the secret has the correct keys
kubectl get secret my-tls-secret -n <namespace> -o jsonpath='{.data}' | jq 'keys'
# Expected: ["tls.crt", "tls.key"]

# Verify the Ingress TLS config references the right secret and host
kubectl get ingress my-ingress -n <namespace> -o jsonpath='{.spec.tls}'
# Expected: [{"hosts":["app.example.com"],"secretName":"my-tls-secret"}]

# Check the certificate is valid and not expired
kubectl get secret my-tls-secret -n <namespace>   -o jsonpath='{.data.tls\.crt}' | base64 -d |   openssl x509 -noout -dates -subject

Step 7: Check path type and routing rules

# View the Ingress routing rules
kubectl get ingress my-ingress -n <namespace> -o yaml | grep -A 20 "rules:"

# Common path type issues:
# Exact: only matches /api exactly, not /api/users
# Prefix: matches /api and everything under it

# For SPAs that need all paths to go to one Service:
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 3000
      - path: /
        pathType: Prefix
        backend:
          service:
            name: spa-service
            port:
              number: 80

# Also check for the SPA routing fix: /fix-nginx-404-on-refresh-spa-routing.html

5. Verification Steps

# Confirm Ingress has an ADDRESS
kubectl get ingress -n <namespace> -w
# Watch for ADDRESS to populate (may take 30-60s for cloud LBs)

# Test with curl using the Host header (before DNS is set up)
INGRESS_IP=$(kubectl get ingress my-ingress -n <namespace> -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -H "Host: app.example.com" http://$INGRESS_IP/

# Test HTTPS
curl -k -H "Host: app.example.com" https://$INGRESS_IP/

# Check Ingress controller logs for your hostname
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller --tail=100 |   grep "app.example.com"

6. Common Mistakes

7. Prevention Tips

8. FAQ

The Ingress ADDRESS shows an IP but browsing to the hostname times out. Why?

The Ingress has been provisioned but DNS isn't pointing to it yet. Either your DNS record hasn't been updated to point to the Ingress IP/hostname, or DNS propagation hasn't completed. Test by hitting the Ingress IP directly with a Host header: curl -H "Host: app.example.com" http://<ingress-ip>/. If that works, the issue is DNS.

The Ingress gives 502 Bad Gateway. What does that mean?

The Ingress controller reached the backend Service but got an error. Check: (1) Service has ready endpoints (kubectl get endpoints), (2) pods are Running and 1/1 ready, (3) the Service port matches what the pods are listening on. A 502 means routing is working — the backend application is the issue.

How do I use the same Ingress for both HTTP and HTTPS?

Configure the tls block in the Ingress spec and add an annotation to redirect HTTP to HTTPS: for NGINX Ingress Controller use nginx.ingress.kubernetes.io/ssl-redirect: "true". For cert-manager TLS automation, add cert-manager.io/cluster-issuer annotation and cert-manager will provision the certificate and populate the TLS secret automatically.

9. Summary

SymptomCauseFix
Ingress ADDRESS is emptyController not running or wrong classCheck controller pods; verify ingressClassName matches
502 Bad GatewayBackend Service has no ready endpointsCheck Service selector and pod readiness
404 on specific pathsPath type mismatch or wrong path specUse Prefix instead of Exact; check path ordering
HTTPS returns certificate errorTLS secret missing or wrong namespaceCheck secret exists in same namespace as Ingress
Works with IP, not hostnameDNS not pointing to Ingress addressUpdate DNS A/CNAME record to Ingress IP or hostname

Explore More in This Category

Explore more in this category: Kubernetes guides. Browse all DevOps Compass articles or jump to: Kubernetes, AWS, CI/CD, Containers, Monitoring, Networking.