What's Actually Happening

Kubernetes Ingress provides HTTP/HTTPS routing to Services. When Ingress doesn't work, requests to the Ingress host don't reach the backend Services. This happens when ingress controller isn't installed, rules are wrong, or backend services aren't ready.

The Error You'll See

```bash $ curl http://my-app.example.com curl: (7) Failed to connect to my-app.example.com port 80: Connection refused

# Or 404/502 from ingress controller $ curl http://my-app.example.com 404 page not found # Ingress controller but no matching rule ```

Why This Happens

  1. 1.Ingress controller not installed - No nginx-ingress, traefik, etc.
  2. 2.Ingress rules wrong - Wrong host, path, or backend service
  3. 3.Backend service not ready - Service has no endpoints
  4. 4.DNS not configured - Domain doesn't point to ingress IP
  5. 5.TLS certificate issues - Certificate not valid or missing
  6. 6.Ingress class mismatch - Ingress uses wrong controller

Step 1: Check Ingress Controller

bash
kubectl get pods -A | grep ingress

Should show ingress controller pods:

bash
ingress-nginx-controller-xxx   1/1   Running   ingress-nginx   nginx-ingress

If missing, install ingress controller:

```bash # NGINX Ingress Controller kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

# Or with Helm helm install ingress-nginx ingress-nginx/ingress-nginx ```

Step 2: Get Ingress Controller IP

bash
kubectl get svc -A | grep ingress

Find the LoadBalancer or NodePort:

bash
ingress-nginx-controller   LoadBalancer   10.96.100.100   192.168.1.100   80:30080/TCP,443:30443/TCP

If LoadBalancer IP pending (bare metal):

```bash # Use NodePort kubectl get svc ingress-nginx-controller -o yaml # Node port: 30080, 30443

# Or check host network kubectl get pods -n ingress-nginx -o wide ```

Step 3: Check Ingress Resource

bash
kubectl get ingress
kubectl describe ingress my-ingress

Output:

bash
Name:             my-ingress
Namespace:        default
Address:          192.168.1.100
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host                Path  Backends
  ----                ----  --------
  my-app.example.com  
                      /   my-service:80 (10.244.1.5:8080,10.244.2.3:8080)
Annotations:         nginx.ingress.kubernetes.io/rewrite-target: /
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  5m    nginx-ingress-controller  Ingress default/my-ingress
  Normal  UPDATE  4m    nginx-ingress-controller  Ingress default/my-ingress

Check: - Address shows ingress IP - Backends show pod IPs (good) - Backends show <error> (problem)

Step 4: Verify Backend Service

bash
kubectl get svc my-service
kubectl get endpoints my-service

Endpoints must have pod IPs:

bash
NAME         ENDPOINTS                       AGE
my-service   10.244.1.5:8080,10.244.2.3:8080  5m

If empty, fix service selector or pod readiness.

Step 5: Check Ingress Rules Configuration

bash
kubectl get ingress my-ingress -o yaml

Check:

yaml
spec:
  rules:
  - host: my-app.example.com  # Must match your domain
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service    # Must exist
            port:
              number: 80        # Must match service port

Common mistakes: - Wrong hostname (doesn't match DNS) - Wrong service name - Wrong port number

Step 6: Test Ingress Controller Directly

```bash # Get ingress IP INGRESS_IP=$(kubectl get svc ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Test with Host header curl -H "Host: my-app.example.com" http://$INGRESS_IP

# Should return app response ```

If this works but real domain fails, DNS is wrong.

Step 7: Check DNS Configuration

```bash # Get ingress IP kubectl get svc ingress-nginx-controller

# Verify DNS points to ingress IP nslookup my-app.example.com dig my-app.example.com

# Should show ingress IP ```

If DNS wrong, update DNS records to point to ingress IP.

Step 8: Check Ingress Class

bash
kubectl get ingressclass
kubectl get ingress my-ingress -o yaml | grep ingressClassName

If ingress uses specific class:

yaml
spec:
  ingressClassName: nginx

Ensure that class exists and controller watches it.

Step 9: Check TLS Configuration

If using HTTPS:

bash
kubectl get ingress my-ingress -o yaml | grep -A10 tls

Check:

yaml
tls:
- hosts:
  - my-app.example.com
  secretName: my-tls-secret

Verify secret:

bash
kubectl get secret my-tls-secret
kubectl describe secret my-tls-secret

Step 10: Check Ingress Annotations

Annotations control ingress controller behavior:

bash
kubectl get ingress my-ingress -o yaml | grep annotations -A10

Common annotations:

yaml
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /$2
  nginx.ingress.kubernetes.io/ssl-redirect: "false"
  nginx.ingress.kubernetes.io/proxy-body-size: "10m"

Verify the Fix

```bash # Test ingress directly curl -H "Host: my-app.example.com" http://$INGRESS_IP

# Test via DNS (after DNS updated) curl http://my-app.example.com

# Check ingress status kubectl describe ingress my-ingress # Address should show IP, Backends should show endpoints ```

Prevention Tips

When creating ingress:

```yaml # Specify ingress class spec: ingressClassName: nginx

# Use exact path type pathType: Prefix # or Exact, ImplementationSpecific

# Ensure backend service exists first kubectl get svc my-service

# Create TLS secret if using HTTPS kubectl create secret tls my-tls-secret --cert=tls.crt --key=tls.key ```