Ravindra BagaleCourses & study guides मराठी

Chapter 18: Kubernetes Workloads

18.12 The Service spreads traffic across ready Pods

Why: the problem

Pods come and go. Every new Pod gets a new IP. If the Myntra cart service talked to the pricing service by Pod IP, it would break on every deploy. A Service fixes this. It gives a group of Pods one stable virtual IP and one DNS name, like pricing. It watches which Pods match its label selector and are ready, and sends each connection to one of them. Pods that fail their readiness probe are removed from the list until they recover. So the Service is also a simple load balancer and a safety net. In this lesson you will put a Service in front of three Pods that print their own name, prove that traffic spreads, make one Pod unready and see it leave the list, and look at the EndpointSlice that holds the real Pod IPs.

What we will build

You will run three http-echo Pods that answer with their Pod name, a ClusterIP Service called who, and a client loop that counts answers. Then you will break readiness on one Pod, scale up, and expose the Service on your laptop with port-forward and NodePort.

What: every term in plain English

  • Service — A stable virtual IP and DNS name for a set of Pods.
  • ClusterIP — The default Service type. Reachable only inside the cluster.
  • NodePort — Opens the same port (30000-32767) on every node.
  • Selector — The labels a Service uses to find Pods.
  • EndpointSlice — The list of ready Pod IPs behind a Service.
  • kube-proxy — The agent on each node that programs iptables or IPVS rules for Services.
  • Readiness — A Pod is added to the Service only when it is ready.
  • port and targetPort — The Service port clients use, and the container port it forwards to.
Start a lab cluster Make a practice namespace Deploy three Pods that say their name See the Service See the endpoints Call it by DNS Port-forward to your laptop
Service spreading traffic across ready Pods

How: step by step

  1. Start a lab cluster

    kind create cluster --name lab
    kubectl get nodes
    

    What it does: Creates a one-node Kubernetes cluster inside Docker. On minikube use: minikube start.

    Output

    Creating cluster "lab" ...
     ✓ Ensuring node image (kindest/node:v1.30.0)
     ✓ Preparing nodes
    Set kubectl context to "kind-lab"
    NAME                STATUS   ROLES           AGE   VERSION
    lab-control-plane   Ready    control-plane   40s   v1.30.0
    
  2. Make a practice namespace

    kubectl create namespace practice
    kubectl config set-context --current --namespace=practice
    

    What it does: Keeps all lab objects in one folder that is easy to delete.

    Output

    namespace/practice created
    Context "kind-lab" modified.
    
  3. Deploy three Pods that say their name

    kubectl apply -f who.yaml
    

    What it does: The file is in Example 1.

    Output

    deployment.apps/who created
    service/who created
    
  4. See the Service

    kubectl get svc who
    

    What it does: A stable ClusterIP.

    Output

    NAME   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)
    who    ClusterIP   10.96.81.200   none          80/TCP
    
  5. See the endpoints

    kubectl get endpointslice -l kubernetes.io/service-name=who
    

    What it does: The real Pod IPs.

    Output

    NAME        ADDRESSTYPE   PORTS   ENDPOINTS
    who-8x2kq   IPv4          5678    10.244.0.11,10.244.0.12,10.244.0.13
    
  6. Call it by DNS

    kubectl run c --rm -it --image=busybox:1.36 --restart=Never -- wget -qO- who
    

    What it does: Any Pod can use the name.

    Output

    who-6b9f7c8d5-4kx2m
    
  7. Port-forward to your laptop

    kubectl port-forward svc/who 8080:80
    

    What it does: Your laptop port 8080 goes to the Service. Ctrl+C to stop.

    Output

    Forwarding from 127.0.0.1:8080 -> 5678
    

Example 1: Three Pods and a ClusterIP Service

Stack. kind, Kubernetes 1.30

Goal. Three Pods and a ClusterIP Service.

who.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: who
spec:
  replicas: 3
  selector:
    matchLabels: {app: who}
  template:
    metadata:
      labels: {app: who}
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo:1.0
        args: ["-text=$(POD_NAME)"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef: {fieldPath: metadata.name}
        ports: [{containerPort: 5678}]
        readinessProbe:
          httpGet: {path: /, port: 5678}
          periodSeconds: 3
---
apiVersion: v1
kind: Service
metadata:
  name: who
spec:
  selector: {app: who}
  ports:
  - port: 80
    targetPort: 5678

What each line does

  • fieldRef metadata.name — Puts the Pod name into an env var.
  • -text=$(POD_NAME) — Each Pod answers with its own name.
  • readinessProbe — Decides if the Pod is in the Service.
  • selector app: who — Matches the three Pods.
  • port 80 targetPort 5678 — Clients use 80; Pods listen on 5678.

Green output

deployment.apps/who created
service/who created
NAME   READY   UP-TO-DATE   AVAILABLE
who    3/3     3            3

Expected result. The Service name who now works from any Pod in the namespace, and as who.practice.svc.cluster.local from others.

Example 2: Prove traffic is spread

Stack. kube-proxy iptables mode

Goal. Prove traffic is spread.

terminal

kubectl run load --image=busybox:1.36 --restart=Never -- sh -c 'for i in $(seq 300); do wget -qO- who; done'
kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/load --timeout=60s
kubectl logs load | sort | uniq -c

What each line does

  • seq 300 — 300 requests.
  • wget -qO- who — Each request opens a new connection, so kube-proxy may pick a new Pod.
  • sort | uniq -c — Counts answers per Pod.

Green output

 97 who-6b9f7c8d5-4kx2m
104 who-6b9f7c8d5-9tqz7
 99 who-6b9f7c8d5-m2vn8

Expected result. Roughly a third each. In iptables mode the choice is random per connection, which evens out.

Example 3: An unready Pod leaves the Service

Stack. EndpointSlice API

Goal. An unready Pod leaves the Service.

terminal

BAD=$(kubectl get pod -l app=who -o name | head -1)
kubectl label $BAD app=who-off --overwrite
kubectl get endpointslice -l kubernetes.io/service-name=who
kubectl get pods -L app
kubectl scale deploy who --replicas=5
kubectl get endpointslice -l kubernetes.io/service-name=who

What each line does

  • label app=who-off — The Pod no longer matches the selector. The same happens when readiness fails.
  • endpointslice — Now lists only matching, ready Pods.
  • New Pod — The Deployment also makes a replacement.
  • scale to 5 — New Pods join the slice as soon as they are ready.

Green output

pod/who-6b9f7c8d5-4kx2m labeled
NAME        ADDRESSTYPE   PORTS   ENDPOINTS
who-8x2kq   IPv4          5678    10.244.0.12,10.244.0.13,10.244.0.14
NAME                  READY   STATUS    APP
who-6b9f7c8d5-4kx2m   1/1     Running   who-off
who-6b9f7c8d5-9tqz7   1/1     Running   who
who-6b9f7c8d5-m2vn8   1/1     Running   who
who-6b9f7c8d5-x7k2p   1/1     Running   who
deployment.apps/who scaled
who-8x2kq   IPv4          5678    10.244.0.12,10.244.0.13,10.244.0.14,10.244.0.15,10.244.0.16

Expected result. The Service list follows labels and readiness in seconds. You never edit IPs by hand.

Verify: did it work?

  1. Check the Service has endpoints

    kubectl describe svc who | grep -E "Selector|Endpoints"
    

    What it does: Empty Endpoints means no Pod matches or none is ready.

    Output

    Selector:          app=who
    Endpoints:         10.244.0.12:5678,10.244.0.13:5678,10.244.0.14:5678 + 2 more...
    
  2. Try NodePort

    kubectl patch svc who -p '{"spec":{"type":"NodePort"}}' && kubectl get svc who && docker exec lab-control-plane curl -s localhost:$(kubectl get svc who -o jsonpath={.spec.ports[0].nodePort})
    

    What it does: Opens a port on the node. Lesson 19 covers all Service types.

    Output

    NAME   TYPE       CLUSTER-IP     PORT(S)
    who    NodePort   10.96.81.200   80:31544/TCP
    who-6b9f7c8d5-9tqz7
    

When it is red 1

Service has no endpoints (Endpoints: none)

Cause. The selector does not match the Pod labels, or no Pod is ready.

Fix, step by step

  1. Compare kubectl get svc who -o yaml selector with kubectl get pods --show-labels.
  2. Check readiness with kubectl describe pod.

When it is red 2

wget: can't connect to remote host (10.96.81.200): Connection refused

Cause. targetPort does not match the port the container listens on.

Fix, step by step

  1. Check the containerPort and the app listen port.
  2. Fix targetPort.

When it is red 3

wget: bad address 'who'

Cause. DNS lookup failed: wrong namespace or CoreDNS is down.

Fix, step by step

  1. Use who.practice.svc.cluster.local.
  2. Run kubectl get pods -n kube-system -l k8s-app=kube-dns.

Cleanup

  1. Delete the lesson objects

    kubectl delete deploy who
    kubectl delete svc who
    kubectl delete pod load --ignore-not-found
    kubectl delete pod -l app=who-off
    

    What it does: Removes the Deployment, Service and leftover Pods.

    Output

    deployment.apps "who" deleted
    service "who" deleted
    
  2. Delete the practice namespace

    kubectl delete namespace practice
    

    What it does: Deletes every object you made in this lesson in one go.

    Output

    namespace "practice" deleted
    

Ravindra Bagale's Tip

Service la ek kayamcha naav ani IP asto. Fakt ready Pods la traffic jaata. Lakshat theva!

Practice tasks

Easy Read a Service

Why: Know the fields.

What to do: Run kubectl get svc who -o yaml and explain each spec field.

How:
  1. Look at selector, ports, type, clusterIP.

Check: You can explain every line.

Medium Session affinity

Why: Some apps need sticky users.

What to do: Set sessionAffinity: ClientIP and send 50 requests from one Pod.

How:
  1. kubectl patch svc who -p spec.sessionAffinity ClientIP
  2. Run the loop.

Check: All answers come from one Pod.

Hard IPVS mode

Why: Big clusters use IPVS.

What to do: Read how kind can set kubeProxyMode: ipvs and try it.

How:
  1. Add networking.kubeProxyMode: ipvs to the kind config.
  2. Run ipvsadm -Ln inside the node.

Check: You see the Service virtual server.

Easy Say how a Service spreads traffic in two lines

Why: If you can say it simply, you understand it. Interviewers want the short version first.

What to do: Write two short lines about how a Service spreads traffic for a fresher who knows only Docker basics.

How:
  1. Write what problem it solves.
  2. Write the one kubectl command you use for it.
  3. Read it aloud to a friend.

Check: A fresher understands it without asking a question.

Easy Start a fresh lab cluster

Why: Practice needs a throwaway cluster. If you break it, you delete it and start again.

What to do: Create a kind cluster, or a minikube cluster, and check the node is Ready.

How:
  1. kind create cluster --name lab
  2. kubectl get nodes
  3. kubectl get pods -A

Check: One node shows STATUS Ready and the kube-system Pods are Running.

Medium Break it on purpose

Why: You must know the red message by face. During an outage there is no time to read slowly.

What to do: Cause one error from the "When it is red" part of this lesson and fix it.

How:
  1. Follow the error section.
  2. Copy the exact message and the kubectl describe Events into your notes.
  3. Write the fix in one line.

Check: You fixed it using only the steps, without searching the web.

Medium Write a one-page runbook

Why: At 2 a.m. nobody remembers the right command. A short page saves the on-call person.

What to do: Write a runbook page for this lesson.

How:
  1. Title, when to use, exact kubectl command, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Repeat it on a cloud cluster

Why: kind is a laptop toy. Real clusters run on EKS, GKE, AKS or k3s on a VM.

What to do: Do the main steps of this lesson again on a small k3s VM or a free-tier managed cluster.

How:
  1. Install k3s on one Ubuntu 22.04 VM: curl -sfL https://get.k3s.io | sh -
  2. Copy the kubeconfig.
  3. Apply the same YAML and compare the output.

Check: Same output on the cloud cluster as on kind.

Hard Explain it like an interview

Why: Interviewers want real stories, not definitions.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the YAML field you used, the kubectl command you ran, and one error you hit.

Check: Your answer has a real command and a real error message.

Hard Draw the flow top to bottom

Why: A drawing shows who talks to whom and in what order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at kubectl apply, go through the API server, controller and scheduler, end at the running container.

Check: Each box matches a real thing you saw in kubectl output.

Homework: try at home

Try at home

At home, run 4 Pods that print their name behind a Service. Send 400 requests and count answers per Pod. Then make one Pod fail its readiness probe and count again.

Recap

  • A Service gives Pods a stable IP and DNS name.
  • It sends traffic only to ready Pods that match its selector.
  • EndpointSlices hold the real Pod IPs.
  • kube-proxy spreads connections across them.
  • port-forward and NodePort reach it from outside.

FAQ

Is a Service a real process?

No. ClusterIP is virtual; kube-proxy rules on each node do the forwarding.

Does a Service retry a failed request?

No. Retries are the client or a service mesh job.

Why did one long connection always hit one Pod?

Balancing is per connection, not per request. HTTP keep-alive reuses one connection.

Endpoints or EndpointSlice?

EndpointSlice is the newer, scalable API. Endpoints still exists for older tools.

What is a headless Service?

clusterIP: None. DNS returns Pod IPs directly; used with StatefulSets.

Interview questions

  1. How does a Service load balance?

    kube-proxy programs iptables or IPVS rules so each new connection to the ClusterIP goes to one ready endpoint.

  2. What happens when a Pod fails readiness?

    It is removed from the EndpointSlice and gets no new traffic until ready again.

  3. Service has no endpoints. What do you check?

    Selector versus Pod labels, readiness, and targetPort.

  4. How does DNS work for Services?

    CoreDNS returns the ClusterIP for NAME.NAMESPACE.svc.cluster.local.

  5. Why not use Pod IPs directly?

    Pod IPs change on every restart and scale event.

Quick quiz

Q1. What does a Service give a set of Pods?

A stable IP and DNS name.

Q2. What decides which Pods are behind a Service?

The label selector and readiness.

Q3. Where are the real Pod IPs listed?

In the EndpointSlice.

Q4. Which component programs the rules on each node?

kube-proxy.

Q5. How do you reach a ClusterIP Service from your laptop?

kubectl port-forward.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards