Kubernetes Fundamentals · Module 06 of 14

Services, DNS and cluster networking

Give changing Pods a stable network identity and understand ClusterIP, selectors, endpoints and in-cluster DNS.

Learning objectives

By the end of this module, you should be able to:

  • Explain why Pod IPs should not be treated as stable service addresses.
  • Create a ClusterIP Service for a Deployment.
  • Resolve and call a Service from another Pod.

Pod IPs are ephemeral identities

Pods can be recreated with different IP addresses. Clients therefore need a stable abstraction that selects healthy matching backends rather than hard-coding individual Pod addresses.

Services provide stable discovery

A ClusterIP Service gets a virtual service address and DNS name within the cluster. Its selector identifies backend Pods; EndpointSlice objects represent the discovered endpoints.

DNS is namespace-aware

A Service named web in namespace gnu-k8s-fundamentals is reachable as web from the same namespace and through a fully qualified service DNS name from elsewhere, subject to network policy and DNS health.

Worked examples

See the idea in practice.

Expose a Deployment internally

kubectl -n gnu-k8s-fundamentals expose deployment web --name=web-svc --port=80 --target-port=80
kubectl -n gnu-k8s-fundamentals get service web-svc
kubectl -n gnu-k8s-fundamentals get endpointslices -l kubernetes.io/service-name=web-svc
  • The Service remains stable while Pods can be replaced.
  • EndpointSlices show the selected backend addresses.
Hands-on lab

Lab — Reach a Service by DNS

Goal: Expose a replicated web Deployment and call it from a temporary client Pod.

Before you start

  • kubectl is installed and can reach the lab cluster.
  • Use the dedicated gnu-k8s-fundamentals namespace unless a step explicitly says otherwise.
STEP 1

Create backend replicas

kubectl -n gnu-k8s-fundamentals create deployment svc-web --image=nginx:alpine
kubectl -n gnu-k8s-fundamentals scale deployment svc-web --replicas=2
kubectl -n gnu-k8s-fundamentals rollout status deployment/svc-web --timeout=120s
STEP 2

Create a ClusterIP Service

kubectl -n gnu-k8s-fundamentals expose deployment svc-web --name=svc-web --port=80 --target-port=80
STEP 3

Inspect Service and endpoints

kubectl -n gnu-k8s-fundamentals get svc svc-web
kubectl -n gnu-k8s-fundamentals get endpointslices -l kubernetes.io/service-name=svc-web
STEP 4

Call the Service through DNS

kubectl -n gnu-k8s-fundamentals run net-client --rm -i --restart=Never --image=busybox:1.36 -- wget -qO- http://svc-web
STEP 5

Clean up

kubectl -n gnu-k8s-fundamentals delete service svc-web
kubectl -n gnu-k8s-fundamentals delete deployment svc-web

Verify

  • The Service has a ClusterIP.
  • EndpointSlices contain backend addresses.
  • The client resolves svc-web and receives nginx content.

Expected outcome

  • The request succeeds without using a Pod IP directly.

If it fails

  • If endpoints are empty, compare Service selector with Pod labels.
  • If DNS fails, test the fully qualified name and inspect cluster DNS Pods.
Real-world connection

Services decouple clients from Pod churn and are the normal in-cluster discovery mechanism for replicated applications.

Avoid these traps

Common mistakes

  • Hard-coding Pod IP addresses in clients.
  • Assuming a Service creates Pods.
  • Using NodePort by default when only in-cluster access is required.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1Why is a Service useful when Pods are replaced?

It provides stable discovery and selects current matching backends.

2What usually determines a Service backend set?

Its label selector.

3Where can you inspect discovered Service endpoints?

EndpointSlice resources.