Kubernetes path · Running and reaching your app · Topic 5 of 13

Services, kube-proxy and DNS

Not started

Pods are replaced all the time, and each replacement gets a new IP. A Service gives a set of pods one stable identity: a name in DNS and, for the usual ClusterIP type, a virtual IP address that never changes while the Service exists. The Service selects pods by label; the control plane continuously records which of those pods are ready in EndpointSlice objects, and a proxy on every node sends connections for the virtual IP to one of them.

Why it matters: Pods come and go with new IPs on every restart. Services are how anything finds them, and most 'it cannot connect' incidents are a selector, a port or readiness.

  1. 1A Service selects pods by label

    Its selector picks the pods; the control plane keeps the list of ready pod IPs in EndpointSlices.

  2. 2A virtual IP that never changes

    A ClusterIP Service gets one stable virtual IP. kube-proxy (iptables mode by default; nftables and IPVS are alternatives) programs every node to spread connections to it across the endpoints.

  3. 3DNS names for free

    CoreDNS answers web.shop.svc.cluster.local, or just web from the same namespace, with the Service's IP.

  4. 4Only ready pods receive traffic

    A pod whose readiness probe fails is removed from the endpoints, while it keeps running.

1

How it works

The explanation, with examples you can run.

The manifest

apiVersion: v1kind: Servicemetadata:  name: webspec:  type: ClusterIP  selector:    app: web              # the pods from the Deployment's template  ports:    - name: http      port: 80            # what clients use      targetPort: 3000    # what the container listens on
kubectl get svc web# NAME   TYPE        CLUSTER-IP     PORT(S)# web    ClusterIP   10.96.41.120   80/TCPkubectl get endpointslices -l kubernetes.io/service-name=web# the ready pod IPs on port 3000

How a connection reaches a pod

  1. The client resolves web. Each pod's /etc/resolv.conf points at the cluster DNS (CoreDNS) with search domains such as shop.svc.cluster.local, so web expands to web.shop.svc.cluster.local and resolves to the ClusterIP.
  2. The client connects to 10.96.41.120:80. No process listens on that address.
  3. On the client's node, rules written by kube-proxy match the virtual IP and rewrite the destination to one endpoint, for example 10.244.2.17:3000.
  4. The pod network delivers the packet to that pod, on whatever node it runs.

kube-proxy watches Services and EndpointSlices and rewrites those rules whenever pods come, go, or change readiness. Its default mode on Linux is still iptables; an nftables mode is available and is planned to become the default, and IPVS mode was deprecated in 1.35. Some network plugins (for example Cilium with eBPF) replace kube-proxy entirely. Load balancing happens per connection, so long-lived connections such as HTTP/2 or gRPC stick to one pod; balance those at layer 7 with a proxy or mesh.

Service types

  • ClusterIP (default): reachable inside the cluster only.
  • NodePort: also opens a port (30000-32767 by default) on every node.
  • LoadBalancer: also asks the cloud provider for an external load balancer pointing at the nodes.
  • Headless (clusterIP: None): no virtual IP; DNS returns the pod IPs directly. StatefulSets use this to give each pod its own name.
  • ExternalName: a DNS alias (CNAME) for something outside the cluster.

When it does not connect

Check in this order:

  • Endpoints empty? The selector does not match the pod labels, or no pod is ready.
  • Wrong port? targetPort must be the port the container listens on (a named port is safest).
  • App bound to 127.0.0.1? It must listen on 0.0.0.0 to accept traffic from outside its own pod.
  • Wrong namespace? Bare names resolve only in the caller's namespace; use name.namespace.
  • NetworkPolicy? A default-deny policy drops traffic that is not explicitly allowed.

Because only ready pods are endpoints, readiness probes are also how a pod takes itself out of traffic during start-up, overload or shutdown.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.A Service has port: 80 and targetPort: 3000. A client in the cluster calls http://web. Where does the connection arrive?
  2. 2.A Service exists, the pods are running, but the Service has no endpoints. What is the most likely cause?
  3. 3.From namespace shop, how do you reach the Service db in namespace data?

0 of 3 right so far. Get all three to finish this topic.