What's Actually Happening
Kubernetes Ingress is configured but traffic is not being routed to services. Requests to the Ingress host return errors or no response.
The Error You'll See
```bash $ curl http://myapp.example.com
404 Not Found ```
Service unavailable:
```bash $ curl http://myapp.example.com/api
503 Service Unavailable ```
Connection refused:
```bash $ curl http://myapp.example.com
curl: (7) Failed to connect to myapp.example.com port 80 ```
Ingress not created:
```bash $ kubectl get ingress
No resources found in default namespace. ```
Why This Happens
- 1.Ingress controller missing - No Ingress controller deployed
- 2.Wrong Ingress class - Ingress class doesn't match controller
- 3.Backend service not found - Service name or port wrong
- 4.Service has no endpoints - Service has no ready pods
- 5.Host DNS not configured - DNS not pointing to Ingress
- 6.TLS certificate missing - HTTPS requires certificate
Step 1: Check Ingress Controller
```bash # Check Ingress controller deployment: kubectl get pods -n ingress-nginx
# Common controllers: # - NGINX Ingress: namespace ingress-nginx or nginx-ingress # - Traefik: namespace traefik # - HAProxy: namespace haproxy-ingress
# Check controller service: kubectl get svc -n ingress-nginx
# Check controller logs: kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
# Check controller config: kubectl get configmap -n ingress-nginx ingress-nginx-controller
# Install NGINX Ingress if missing: kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
# Or with Helm: helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx ```
Step 2: Check Ingress Resource
```bash # Check Ingress exists: kubectl get ingress
# Check Ingress details: kubectl describe ingress my-ingress
# Check Ingress YAML: kubectl get ingress my-ingress -o yaml
# Verify Ingress class: kubectl get ingress my-ingress -o jsonpath='{.spec.ingressClassName}'
# Check rules: kubectl get ingress my-ingress -o jsonpath='{.spec.rules}'
# Check default backend: kubectl get ingress my-ingress -o jsonpath='{.spec.defaultBackend}'
# Example Ingress: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: myapp.example.com http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80 ```
Step 3: Check Backend Service
```bash # Check service exists: kubectl get svc my-service
# Check service details: kubectl describe svc my-service
# Check service port matches Ingress: kubectl get svc my-service -o jsonpath='{.spec.ports}'
# Check service type: kubectl get svc my-service -o jsonpath='{.spec.type}'
# Service should be ClusterIP (or NodePort/LoadBalancer for direct access)
# Check service selector: kubectl get svc my-service -o jsonpath='{.spec.selector}'
# Verify selector matches pods: kubectl get pods -l app=my-app ```
Step 4: Check Service Endpoints
```bash # Check endpoints: kubectl get endpoints my-service
# Endpoints should have pod IPs: # NAME ENDPOINTS # my-service 10.244.0.5:8080,10.244.0.6:8080
# If no endpoints, pods are not selected or not ready
# Check endpoint details: kubectl describe endpoints my-service
# Check pod readiness: kubectl get pods -l app=my-app
# Pods must be Ready (1/1) to be in endpoints
# Check pod labels match service selector: kubectl get pods --show-labels
# Check pod ports: kubectl get pods -l app=my-app -o jsonpath='{.items[0].spec.containers[0].ports}' ```
Step 5: Check Ingress Class
```bash # List Ingress classes: kubectl get ingressclasses
# Check Ingress class: kubectl describe ingressclass nginx
# Check controller handles the class: kubectl get ingressclass nginx -o yaml
# Ingress class example: apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx spec: controller: k8s.io/ingress-nginx
# Ingress must reference correct class: spec: ingressClassName: nginx
# Or use annotation (older method): metadata: annotations: kubernetes.io/ingress.class: nginx
# Check default Ingress class: kubectl get ingressclass -o jsonpath='{.items[?(@.metadata.annotations["ingressclass.kubernetes.io/is-default-class"]=="true")].metadata.name}' ```
Step 6: Check DNS Configuration
```bash # Check DNS points to Ingress: dig myapp.example.com
# Should resolve to Ingress controller IP
# Check Ingress controller IP: kubectl get svc -n ingress-nginx ingress-nginx-controller
# For LoadBalancer type, use external IP # For NodePort, use node IP + port
# Check with nslookup: nslookup myapp.example.com
# Test with IP directly: curl -H "Host: myapp.example.com" http://INGRESS_IP
# For local testing: curl --resolve myapp.example.com:80:INGRESS_IP http://myapp.example.com ```
Step 7: Check Ingress Annotations
```bash # Common annotations: # nginx.ingress.kubernetes.io/rewrite-target: / # nginx.ingress.kubernetes.io/ssl-redirect: "false" # nginx.ingress.kubernetes.io/proxy-body-size: "10m"
# Check annotations: kubectl get ingress my-ingress -o jsonpath='{.metadata.annotations}'
# Check annotation effect: kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx | grep -i my-ingress
# Common issues with annotations: # - Wrong annotation format # - Annotation for wrong controller # - Missing required annotation
# Example rewrite: annotations: nginx.ingress.kubernetes.io/rewrite-target: /api/$2 # With path: /something(/|$)(.*) ```
Step 8: Check TLS Configuration
```bash # Check TLS in Ingress: kubectl get ingress my-ingress -o jsonpath='{.spec.tls}'
# TLS example: spec: tls: - hosts: - myapp.example.com secretName: my-tls-secret
# Check secret exists: kubectl get secret my-tls-secret
# Check secret type: kubectl get secret my-tls-secret -o jsonpath='{.type}' # Should be kubernetes.io/tls
# Check secret data: kubectl get secret my-tls-secret -o yaml
# Create TLS secret: kubectl create secret tls my-tls-secret \ --cert=tls.crt \ --key=tls.key
# Test HTTPS: curl -k https://myapp.example.com
# Check certificate: openssl s_client -connect myapp.example.com:443 -servername myapp.example.com ```
Step 9: Check Ingress Controller Config
```bash # NGINX Ingress ConfigMap: kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml
# Check controller config: kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --config
# Common ConfigMap settings: data: use-forwarded-headers: "true" compute-full-forwarded-for: "true" proxy-buffer-size: "16k"
# Check controller service: kubectl describe svc -n ingress-nginx ingress-nginx-controller
# For NodePort, check ports: kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.spec.ports}'
# Port format: # 80:31234/TCP (http) # 443:31345/TCP (https) ```
Step 10: Kubernetes Ingress Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-k8s-ingress.sh #!/bin/bash
INGRESS=${1:-""} NAMESPACE=${2:-"default"}
echo "=== Ingress Controller Status ===" kubectl get pods -n ingress-nginx -o wide 2>/dev/null || kubectl get pods -A -l app.kubernetes.io/name=ingress-nginx
echo "" echo "=== Ingress Controller Service ===" kubectl get svc -n ingress-nginx 2>/dev/null || kubectl get svc -A -l app.kubernetes.io/name=ingress-nginx
echo "" echo "=== Ingress Classes ===" kubectl get ingressclasses
echo "" echo "=== Ingress Resources ===" kubectl get ingress -n $NAMESPACE
if [ -n "$INGRESS" ]; then echo "" echo "=== Ingress Details: $INGRESS ===" kubectl describe ingress $INGRESS -n $NAMESPACE
echo "" echo "=== Backend Service ===" SERVICE=$(kubectl get ingress $INGRESS -n $NAMESPACE -o jsonpath='{.spec.rules[0].http.paths[0].backend.service.name}') kubectl get svc $SERVICE -n $NAMESPACE kubectl get endpoints $SERVICE -n $NAMESPACE
echo "" echo "=== Service Pods ===" SELECTOR=$(kubectl get svc $SERVICE -n $NAMESPACE -o jsonpath='{.spec.selector}') kubectl get pods -n $NAMESPACE -l $(echo $SELECTOR | tr ':' '=' | tr ',' ' ') fi
echo "" echo "=== Ingress Controller Logs (last 20) ===" kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=20 2>/dev/null || echo "No logs found"
echo "" echo "=== DNS Test ===" if [ -n "$INGRESS" ]; then HOST=$(kubectl get ingress $INGRESS -n $NAMESPACE -o jsonpath='{.spec.rules[0].host}') if [ -n "$HOST" ]; then dig $HOST +short fi fi EOF
chmod +x /usr/local/bin/check-k8s-ingress.sh
# Usage: /usr/local/bin/check-k8s-ingress.sh my-ingress default
# Quick check: alias k8s-ingress='kubectl get ingress -A' ```
Kubernetes Ingress Checklist
| Check | Command | Expected |
|---|---|---|
| Ingress controller | get pods -n ingress-nginx | Running |
| Ingress resource | get ingress | Created |
| Ingress class | get ingressclasses | Matches controller |
| Backend service | get svc | Exists and matches |
| Service endpoints | get endpoints | Has pod IPs |
| DNS resolution | dig hostname | Points to Ingress IP |
Verify the Fix
```bash # After fixing Ingress routing
# 1. Check Ingress controller kubectl get pods -n ingress-nginx // All Running
# 2. Check Ingress resource kubectl get ingress my-ingress // Created with correct class
# 3. Check backend service kubectl get svc my-service // Exists with correct port
# 4. Check endpoints kubectl get endpoints my-service // Has pod IPs
# 5. Test routing curl http://myapp.example.com // Returns application response
# 6. Check logs kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx // No routing errors ```
Related Issues
- [Fix Kubernetes Service Not Found](/articles/fix-kubernetes-service-not-found)
- [Fix Kubernetes Pod CrashLoopBackOff](/articles/fix-kubernetes-pod-crashloopbackoff)
- [Fix Kubernetes Deployment Not Working](/articles/fix-kubernetes-deployment-not-working)