Skip to content

Kubernetes Request Flow: How Traffic Reaches Your Pod

Core Concept LearningJuly 6, 20265 min readUpdated July 21, 2026

When GET https://app.example.com/api/orders/42 returns 502, the failure may sit at DNS, the external load balancer, an Ingress controller, a Service selector, a readiness probe, or the application itself. Kubernetes gives each layer a different object and diagnostic signal. The Layer 4 vs Layer 7 load-balancing guide explains what the external and HTTP-aware hops can inspect.

Trace that one request from the browser to a ready Pod, then isolate a broken route with pasteable manifests and kubectl checks. The exact packet implementation varies by cluster networking stack, but the object-level debugging path remains useful. If NGINX implements your Ingress, the NGINX gateway guide covers its proxy, TLS, routing, and timeout behavior.

Request path: User → DNS → Load Balancer → Ingress → Service → Pod → Container
Request path: User → DNS → Load Balancer → Ingress → Service → Pod → Container

User, DNS, and Load Balancer

The journey starts when a user opens a URL like https://app.example.com. The browser does not know your cluster — it asks public DNS to resolve the hostname. DNS returns the external IP of your cloud load balancer (AWS NLB/ALB, GCP Load Balancer, Azure LB) or the IP exposed by your Ingress controller.

The load balancer sits at the cluster edge. It terminates TLS (or passes it through), accepts TCP/HTTP traffic from the internet, and forwards it into the cluster network. Without this layer, Pod IPs would be unreachable from outside — they live on private cluster networks that are not routable on the public internet.

Steps 1–3: user opens a URL, DNS resolves, load balancer accepts traffic
Steps 1–3: user opens a URL, DNS resolves, load balancer accepts traffic

Quick reference

  • User sends HTTP request to a public hostname.
  • DNS resolves domain → external load balancer IP.
  • Load balancer receives traffic and forwards into the cluster.
  • Use health checks on the LB so unhealthy nodes are removed.
  • TLS can terminate at LB, Ingress, or both (double encryption).
  • Cloud LB type matters: L4 (TCP) vs L7 (HTTP routing).

Remember this

DNS points users at the load balancer — the front door into your Kubernetes cluster.

Ingress, Gateway, and Service

Inside the cluster, Ingress (or the newer Gateway API) performs HTTP/HTTPS routing. It reads rules like "host = app.example.com, path = /api → backend-service" and forwards the request to the correct internal Service. Ingress controllers (NGINX, Traefik, AWS ALB Ingress Controller) watch Ingress resources and configure themselves dynamically.

A Service gives your app a stable virtual IP and DNS name (backend-service.production.svc.cluster.local) even though Pod IPs change constantly. Services do not run code — they are a routing abstraction. ClusterIP Services are internal-only; LoadBalancer and NodePort types expose Services externally (often via cloud LB integration).

Steps 4–5: Ingress routes by host/path; Service provides a stable virtual endpoint
Steps 4–5: Ingress routes by host/path; Service provides a stable virtual endpoint

Quick reference

  • Ingress/Gateway routes by hostname and URL path.
  • Service provides a stable endpoint — hides Pod churn.
  • Ingress: mature, HTTP-focused — most clusters use it today.
  • Gateway API: successor with richer L4/L7 routing models.
  • ClusterIP: default internal Service type.
  • Internal DNS: service-name.namespace.svc.cluster.local.
Deployment and Service — ready backends
1apiVersion: apps/v12kind: Deployment3metadata:4  name: orders5spec:6  replicas: 27  selector:8    matchLabels: { app: orders }9  template:10    metadata:11      labels: { app: orders }12    spec:13      containers:14        - name: api15          image: registry.example.com/orders:1.0.016          ports: [{ containerPort: 8080 }]17          readinessProbe:18            httpGet: { path: /health, port: 8080 }19---20apiVersion: v121kind: Service22metadata:23  name: backend-service24spec:25  selector: { app: orders }26  ports: [{ port: 80, targetPort: 8080 }]
Ingress — route the concrete request
1apiVersion: networking.k8s.io/v12kind: Ingress3metadata:4  name: orders5spec:6  rules:7    - host: app.example.com8      http:9        paths:10          - path: /api11            pathType: Prefix12            backend:13              service:14                name: backend-service15                port: { number: 80 }

Remember this

Ingress picks the right Service; the Service is the stable name your app is known by inside the cluster.

EndpointSlices and Service Forwarding

EndpointSlices track the Pod IPs and ports selected by a Service, including readiness conditions used by traffic-routing components. When an orders Pod fails readiness, it stops being an eligible backend even though the container may still be running.

In many clusters, kube-proxy programs iptables or IPVS rules that translate a Service virtual IP to an endpoint. Some CNI implementations replace kube-proxy with eBPF-based service handling. Backend selection and the client-visible failure vary by implementation and proxy layer; with no ready endpoints, expect a failed connection or an upstream 503 rather than a request reaching the app.

Steps 6–8: EndpointSlices track healthy Pods; kube-proxy forwards to a selected Pod
Steps 6–8: EndpointSlices track healthy Pods; kube-proxy forwards to a selected Pod

Quick reference

  • EndpointSlice lists ready Pod IP:port pairs.
  • kube-proxy forwards Service traffic to a Pod.
  • Readiness probes control EndpointSlice membership.
  • Liveness probes restart crashed containers.
  • No ready endpoints → 503 / connection refused.
  • Service handling may use kube-proxy (iptables/IPVS) or a CNI eBPF replacement.

Remember this

A Service has no listening process of its own — kube-proxy (or the CNI's eBPF path) programs forwarding rules straight from EndpointSlices.

Pod, Container, and Response

The request reaches a Pod — the smallest deployable unit in Kubernetes, with one or more containers sharing a network namespace. Traffic arrives on the Pod IP at the target port selected by the Service.

The application builds a response on the established connection. Return packets are routed and any connection-tracking/NAT state is reversed as required, but they are not guaranteed to traverse the identical proxies or network devices in reverse. A Service is a virtual-IP/routing abstraction, not necessarily a distinct reverse-path hop.

Steps 9–10: container handles the request; response returns along the same path
Steps 9–10: container handles the request; response returns along the same path

Quick reference

  • Request arrives at the selected Pod via the cluster network.
  • Application container processes the request.
  • Response follows connection and routing state back through the applicable proxy/LB path; asymmetric network paths are possible.
  • Pod IP is ephemeral — never hardcode it in clients.
  • Sidecar containers in the same Pod share localhost networking.
  • NetworkPolicies can restrict which Pods may talk to each other.

Remember this

Pods are ephemeral; Services and Ingress give the outside world a stable way to reach them.

Important Notes for Production

Several details catch teams off guard in real clusters. Services hide changing Pod IPs — always call other workloads by Service DNS, never by Pod IP. Ingress handles external HTTP routing; internal service-to-service calls use ClusterIP DNS directly, skipping Ingress entirely.

The internal DNS pattern is service-name.namespace.svc.cluster.local — for example backend-service.production.svc.cluster.local. Short names like backend-service work within the same namespace. Gateway API is gradually replacing Ingress for advanced routing (header-based rules, traffic splitting, TLS management), but the conceptual flow remains the same.

When debugging, trace the path: can DNS resolve? Does the LB health check pass? Does Ingress have the right host rule? Does the Service have endpoints (kubectl get endpointslices)? Is the Pod ready?

Zoom into one Kubernetes request excluded by readiness
Zoom into one Kubernetes request excluded by readiness

Quick reference

  • Never call Pod IPs directly — use Service DNS.
  • External traffic: User → LB → Ingress → Service → Pod.
  • Internal traffic: Pod → Service DNS → Pod (skips Ingress).
  • kubectl get endpointslices -n <ns> — see ready backends.
  • 502 often means Ingress cannot reach Service or no endpoints.
  • Gateway API: modern replacement for Ingress routing.
Isolate the failing layer
1kubectl apply -f orders.yaml2kubectl get ingress,service,pods3kubectl get endpointslices \4  -l kubernetes.io/service-name=backend-service5kubectl describe ingress orders6kubectl describe service backend-service
Bypass Ingress, then recover
1kubectl port-forward service/backend-service 8080:802curl --fail http://localhost:8080/api/orders/423 4# Empty EndpointSlice? Inspect readiness and logs5kubectl describe pod -l app=orders6kubectl logs deployment/orders7# Restore the previous working Deployment revision if needed8kubectl rollout undo deployment/orders

Remember this

Debug the chain top-down: DNS → LB → Ingress rules → Service endpoints → Pod readiness.

Key takeaway

Debug Kubernetes traffic by proving one boundary at a time: public DNS and load balancer, Ingress rule, Service selector and port, EndpointSlice readiness, then the application. Do not jump straight to restarting Pods; a selector or route bug survives every restart.

Practice (30 min): On a local cluster with an Ingress controller, apply the article manifests and map app.example.com; the request to /api/orders/42 should reach a Ready orders Pod. Intentionally change the Service selector so the EndpointSlice has no backend. Recover by restoring the selector, verify the app independently with kubectl port-forward, then retry through Ingress. Pass when you capture the failed request, empty-backend evidence, successful direct check, and successful end-to-end request after repair.

Share:

Related Articles

Many teams still introduce NGINX as “just a web server.” In production it usually sits in front of your app: clients hit

Read

Microservices are not a shopping list. They are a set of layers — package, store, communicate, protect the edge, run and

Read

Docker and Kubernetes are not competitors on the same layer, and treating them as an either/or is the mistake that leads

Read

Explore this topic

Keep learning

Follow a structured path or browse all courses to go deeper.