6.9 Service, Endpoint & Ingress Connectivity Troubleshooting
Key Takeaways
Kubernetes Service routing depends on accurate label selector matching; if a Service's 'spec.selector' does not match the target Pod's 'metadata.labels', no Endpoints or EndpointSlices will be populated (Endpoints will show '<none>').
A Pod will be omitted from Service Endpoints even if labels match if the Pod's readinessProbe is failing or if the Pod is not in the 'Running' phase.
Port mapping mismatches are a frequent source of connectivity failures: 'spec.ports[].port' is the external port exposed by the Service, while 'spec.ports[].targetPort' must match the container's active listening port.
Ingress routing failures occur due to missing IngressClasses, path routing mismatches (Prefix vs Exact vs ImplementationSpecific), rewrite annotation omissions, or backend Service name/port discrepancies.
Systematic network debugging utilizes interactive test pods ('kubectl run tmp-shell --rm -it --image=busybox:1.36') to execute 'nslookup', 'nc -zv', and 'curl' across every hop of the network path.
6.9 Service, Endpoint & Ingress Connectivity Troubleshooting
Networking in Kubernetes operates across multiple virtual layers: container virtual ethernet pairs (veth), CNI flat routing, virtual ClusterIP load-balancing via kube-proxy, cluster-internal DNS resolution via CoreDNS, and HTTP/HTTPS layer 7 ingress routing.
When a client or frontend microservice cannot communicate with a backend service, administrators must isolate the exact hop where traffic is dropped.
1. End-to-End Traffic Path & Hop-by-Hop Triage
+-----------------------------------------------------------------------------------------+
| END-TO-END SERVICE TRAFFIC PIPELINE |
| |
| [CLIENT POD] |
| | |
| v (1. Resolves DNS: backend-svc.default.svc.cluster.local -> 10.96.0.50) |
| [CoreDNS] |
| | |
| v (2. Sends packet to ClusterIP 10.96.0.50:80) |
| [KUBE-PROXY / IPTABLES / IPVS on Host Kernel] |
| - Matches DNAT rule for 10.96.0.50:80 |
| - Randomly selects backend Pod IP from Endpoints / EndpointSlices (e.g., 10.244.1.25) |
| - Rewrites destination IP to 10.244.1.25:8080 (targetPort) |
| | |
| v (3. CNI Routes packet across node network overlay) |
| [TARGET BACKEND POD (10.244.1.25)] |
| - Listens on container port 8080 |
| - Readiness probe must be PASSING (otherwise omitted from Endpoints) |
+-----------------------------------------------------------------------------------------+
2. Service & Endpoints Diagnostic Checklist
When a ClusterIP or NodePort Service fails to route traffic, execute this sequential 5-step checklist:
# Step 1: Verify the Service exists and has an assigned ClusterIP
kubectl get svc backend-svc
# Step 2: Check if Endpoints and EndpointSlices exist for the service
kubectl get endpoints backend-svc
kubectl get endpointslices -l kubernetes.io/service-name=backend-svc
Case A: Endpoints displays <none>
If kubectl get endpoints backend-svc shows ENDPOINTS: <none>, traffic cannot be routed because the Service has zero healthy backend pods.
[TROUBLESHOOTING ZERO ENDPOINTS]
1. Check Service Selector: $ kubectl get svc backend-svc -o jsonpath='{.spec.selector}'
Output: map[app:web-backend env:prod]
2. Check Pod Labels: $ kubectl get pods --show-labels
Output: pod-1: app=web-backend, env=production <-- MISMATCH! (prod vs production)
3. Check Pod Health: $ kubectl get pods -l app=web-backend
- If Pods are Running but 0/1 Ready -> Readiness probe is failing!
Important
A pod is added to an Endpoints object only if:
- All key-value pairs in
service.spec.selectormatch the pod'smetadata.labels. - The pod is in the
Runningphase. - The pod's
readinessProbeis succeeding (or no readiness probe is configured).
Case B: Endpoints Populated, But Connection Refused / Times Out
If endpoints exist (e.g., 10.244.1.25:8080), but curling the ClusterIP fails:
# Verify port mapping configuration in Service spec
kubectl get svc backend-svc -o yaml
spec:
ports:
- name: http
port: 80 # Port exposed on the Service ClusterIP
targetPort: 8080 # Port where application container actually listens
protocol: TCP
- TargetPort Mismatch: If the application inside the container listens on port
3000, buttargetPortis set to8080, packets reach the pod but the Linux kernel returns TCP RST (Connection Refused). - Named Port Typo: If
targetPort: http-webis used, ensure the container spec containsports: [{name: http-web, containerPort: 8080}].
3. Ingress Routing & Controller Diagnostics
An Ingress resource is merely a set of rules; traffic routing requires an active Ingress Controller (e.g., ingress-nginx).
+-----------------------------------------------------------------------------------------+
| INGRESS ARCHITECTURAL FLOW |
| |
| External Client ---> [Ingress Controller (e.g., NGINX Pod / NodePort / LB)] |
| | |
| +---> Evaluates Host: app.example.com |
| +---> Evaluates Path: /api (Prefix matching) |
| | |
| v (Routes directly to Pod IPs from Endpoints) |
| [Backend Pods] |
+-----------------------------------------------------------------------------------------+
High-Frequency Ingress Issues & Solutions:
-
Missing or Mismatched
ingressClassName:spec: ingressClassName: nginx # Must match an existing IngressClass: kubectl get ingressclass -
Path Type Matching (
PrefixvsExact):pathType: Exactmatching/apiwill NOT match/api/v1/users.- Use
pathType: Prefixwithpath: /api.
-
Rewrite Annotation Omission: If incoming traffic hits
app.example.com/api/users, but the backend application expects requests at/users, include the NGINX rewrite annotation:metadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: app.example.com http: paths: - path: /api(/|$)(.*) pathType: ImplementationSpecific backend: service: name: backend-svc port: number: 80 -
Inspect Ingress Controller Logs:
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100
4. In-Cluster Connectivity Debugging Runbook
To prove whether a failure is DNS-related, Service-related, or container-related, run a temporary interactive test container:
# 1. Launch a temporary debugging pod
kubectl run tmp-net --rm -it --image=busybox:1.36 --restart=Never -- /bin/sh
# --- Inside the test container shell ---
# 2. Test DNS resolution of the service name
nslookup backend-svc
nslookup backend-svc.default.svc.cluster.local
# 3. Test TCP port reachability on ClusterIP
nc -zv 10.96.0.50 80
# 4. Test HTTP payload response
wget -qO- http://backend-svc:80/healthz
# 5. Test direct Pod IP connectivity (Bypassing Service layer)
# Retrieve Pod IP: kubectl get pods -l app=backend -o wide
wget -qO- http://10.244.1.25:8080/healthz
A developer creates a Service named auth-api to expose a deployment. However, running kubectl get endpoints auth-api displays ENDPOINTS: <none>. The administrator verifies that 3 deployment pods exist and are in the Running phase. What is the most probable cause of this issue?
The cluster CNI plugin has run out of IP addresses.
The kube-proxy daemonset was deleted.
The key-value pairs in spec.selector of the Service do not match the metadata.labels on the pods, or the pods' readiness probes are failing.
The Service was created without specifying an externalIP.
An administrator is inspecting a Service definition with the following configuration:
spec:
ports:
- port: 80
targetPort: 8080
When curling the Service ClusterIP on port 80 from inside a test pod, the connection is instantly rejected with Connection refused. Direct curl requests to the target pod IP on port 3000 succeed. What is the root cause?
The Service type must be changed from ClusterIP to NodePort.
The port and targetPort values must always be identical.
The Service's targetPort is configured as 8080, but the container application is actively listening on port 3000.
CoreDNS is failing to resolve the targetPort name.
An Ingress resource configured for host: portal.example.com with path: /store returns HTTP 404 Not Found from the Ingress Controller when users access http://portal.example.com/store/products. The backend service functions properly when queried directly. What configuration error is present in the Ingress resource?
The Ingress resource was created in the kube-system namespace.
The Ingress rule specifies pathType: Exact instead of pathType: Prefix (or lacks the necessary URL rewrite annotations for the subpath).
The Ingress controller requires spec.tls to be defined for all HTTP paths.
The backend Service must be of type LoadBalancer.
Sections you finish are checked off in the contents.