Courseiva
CKADChapter 14 of 18Objective 6.1

Services, Service Types, and Load Balancing

Services, the vital mechanism for exposing your applications to the world (or to other parts of your application) without breaking when Pods die and get recreated. For the CKAD exam, you must know how to create and configure Services to make your apps reachable, and this chapter gives you the mental model you need to choose the right type and troubleshoot when packets go missing.

12 min read
Beginner
Updated Jul 23, 2026
Editorial oversight: Johnson Ajibi· Security Systems Architect · MSc IT Security · IEEE Senior Member

A simple way to picture Services, Service Types, and Load Balancing

The Apartment Building Mailroom Analogy

You just moved into a big apartment building. Your friends know you live at 742 Evergreen Terrace, but they don't know which flat is yours. How will they get your birthday card to you?

In the old way of doing things, you'd tell everyone your exact flat number, say Flat 4B. Every time a package arrived, you'd have to sit by your front door waiting for the courier. If you moved to Flat 5A next month, you'd have to call every friend and update your address. This is what it was like before Kubernetes Services. Each Pod had its own IP address (its own apartment number), and if a Pod crashed or moved, the IP changed. Everything broke.

Now think about the mailroom in your building's lobby. You tell everyone, 'Send stuff to 742 Evergreen Terrace — the mailroom will get it to me.' The mailroom has a simple list: 'Flat 4B gets Jane's mail, Flat 5A gets John's.' If you move flats, the mailroom just updates its list. You don't have to tell the whole world. That's a Kubernetes Service. It provides a stable, permanent address (the mailroom) that sits in front of your Pods (the flats). If a Pod dies and a new one starts on a different IP, the Service automatically updates its routing list. Your users never know anything changed.

The mailroom can also be clever. If lots of letters arrive, it can split them evenly between two occupied flats. That's load balancing. And if you want to allow delivery drivers to leave packages outside the building altogether, you'd put a delivery box on the street — that's a different Service type, like a NodePort or LoadBalancer. Each type controls exactly how people on the outside reach you.

How It Actually Works

In Kubernetes, a Pod is the smallest deployable unit: it runs your container. But Pods are temporary. They can crash, be deleted, or get rescheduled onto a different worker node, which gives them a new IP address every time. If another Pod or an external user tries to reach a Pod using its IP, it will fail as soon as that Pod moves. A Service solves this by providing a stable, virtual IP address and hostname that never changes, no matter how often the Pods behind it come and go.

A Service is a Kubernetes resource, just like a Pod or a Deployment. You define it in a YAML file. The key fields are the selector (which Pods to target) and the ports (which network port to listen on). The Service continuously watches the cluster for Pods whose labels match the selector. It then updates its internal list of endpoints — the actual IP addresses of the matching Pods. This is called the endpoint slice.

When traffic arrives at the Service's stable IP, the kube-proxy component running on every node intercepts the request and forwards it to one of the healthy Pods. By default, it uses round-robin load balancing, meaning each new connection goes to the next Pod in the list. This spreads the work evenly and prevents one Pod from being overwhelmed.

There are four main Service types, each controlling who can reach the Service:

ClusterIP: The default type. The Service gets a virtual IP that is only reachable from inside the cluster. Other Pods can talk to it, but nothing outside the cluster can. This is perfect for internal communication, like a database Pod being accessed by a web app Pod.

NodePort: This builds on ClusterIP. It exposes the Service on a static port (between 30000 and 32767) on every node in the cluster. If you know a node's IP address and the NodePort, you can reach the Service from outside the cluster by visiting http://node-ip:node-port. This is useful for development or simple tests.

LoadBalancer: This builds on NodePort. It provisions an external load balancer from your cloud provider (like AWS ELB or Google Cloud Load Balancer) and automatically configures it to forward traffic to the NodePort on each node. This is the standard way to expose a production application to the internet.

ExternalName: This does not proxy traffic at all. Instead, it returns a CNAME record pointing to an external address. When a Pod looks up the Service name via DNS, it gets the external hostname back. This is useful for making an external database or API look like a local Service.

Why does this matter? Before Services, every time you deployed a new version of your app, the Pod IPs changed, and every client had to update their configuration. Services decouple the client from the Pods. The client only needs to know the Service name. Kubernetes handles the rest: it watches for Pod changes, updates the endpoint list, and forwards traffic to healthy Pods only. This makes your application resilient to failures and rolling updates.

Load balancing is automatic. You do not need to configure a separate load balancer inside the cluster most of the time. kube-proxy handles it using iptables rules or IPVS. However, if you need session affinity (sticky sessions, where the same client always goes to the same Pod), you can set sessionAffinity: ClientIP on the Service.

To see your Services, use kubectl get svc. To describe a Service, use kubectl describe svc my-service. When trouble arises, check that the selector labels match the Pod labels exactly. A common mistake is a typo in the label: kubectl get pods --show-labels helps you verify.

Flow of traffic from an external client through a LoadBalancer Service to Pods, showing the stable Service IP and the role of kube-proxy.

Walk-Through

1

Define the Pod label scheme

Before creating a Service, decide how you will label your Pods. A common pattern is app: myapp and tier: frontend. The Service will use these exact labels in its selector field. Without matching labels, the Service will have no endpoints.

2

Write the Service YAML

Create a file like service.yaml with apiVersion: v1, kind: Service, metadata.name, and spec. Choose the type (ClusterIP, NodePort, or LoadBalancer). Set the selector to match your Pod labels. Define one or more ports with port and targetPort.

3

Apply the Service to the cluster

Run kubectl apply -f service.yaml. The Kubernetes API validates the manifest and stores it in etcd. The control plane configures kube-proxy on every node to start routing traffic according to the new Service definition.

4

Verify the Service is created

Use kubectl get svc your-service-name to see the Service's cluster IP, external IP (if applicable), and port mappings. If the type is LoadBalancer, the EXTERNAL-IP may show 'pending' until the cloud provider provisions the load balancer.

5

Check endpoints are populated

Run kubectl get endpoints your-service-name. If the ENDPOINTS column shows IP addresses, the Service has successfully matched your Pods. If empty, check your selector labels and that the Pods are running and passing readiness probes.

6

Test connectivity from within the cluster

Run a temporary test Pod with kubectl run test-pod --image=busybox --restart=Never -- sleep 3600, then exec into it with kubectl exec -it test-pod -- sh. Use wget -O- http://your-service-name:port to confirm traffic reaches the Pods. Delete the test Pod using kubectl delete pod test-pod.

What This Looks Like on the Job

You work as a junior DevOps engineer for 'QuickCart', an e-commerce startup. The team has just containerised the backend API with a Deployment running three replicas. The API listens on port 8080. Management wants the public internet to access it. Here is exactly what you do.

First, you create a LoadBalancer Service. Your YAML looks like this:

apiVersion: v1 kind: Service metadata: name: quickcart-api spec: type: LoadBalancer selector: app: quickcart tier: backend ports: - protocol: TCP port: 80 targetPort: 8080

The selector matches Pods that have both labels app: quickcart and tier: backend. Your Deployment template must include those exact labels. The port 80 is what external clients see; targetPort 8080 is what the Pod actually listens on.

You apply the file: kubectl apply -f service.yaml. Within a minute, the cloud provider (AWS, GCP, or Azure) provisions a load balancer and gives you an external IP. You run kubectl get svc quickcart-api and see the EXTERNAL-IP column populated, for example, 203.0.113.42.

Now you test it. You open a browser and visit http://203.0.113.42. The request hits the load balancer, which forwards it to one of your worker nodes on the NodePort (Kubernetes automatically assigned one, say 31456). The node's kube-proxy intercepts the port 80 traffic (because the LoadBalancer's target is port 80 on the node) and sends it to a healthy Pod running on port 8080. Your API responds.

A week later, you deploy a new version of the API. You update the Deployment image. Kubernetes performs a rolling update. Old Pods are terminated, new Pods start. Their IPs change. But your Service never skips a beat because it constantly watches the Pod labels and updates its endpoints in real time. Users keep accessing http://203.0.113.42 and everything works.

What happens in production? - The cloud load balancer performs health checks by hitting the NodePort on each node. If a node goes down, the load balancer stops sending traffic to it. - kube-proxy on each node maintains iptables rules that rewrite the destination IP from the Service IP to a Pod IP. This is fast and efficient. - If a Pod becomes unhealthy (its readiness probe fails), Kubernetes removes it from the Service's endpoint list. Traffic stops going to it immediately, without manual intervention. - If traffic spikes, you can scale your Deployment to 10 replicas. The Service automatically discovers the new Pods and load balances across them.

You also set up a second Service of type ClusterIP for internal communication between the frontend and the API. The frontend Deployment uses the DNS name quickcart-api.default.svc.cluster.local to reach the API. This never changes, so developers can hard-code it in their config.

When debugging, you use: - kubectl describe svc quickcart-api — shows endpoints and selector. - kubectl get endpoints quickcart-api — lists actual Pod IPs the Service is sending traffic to. - kubectl exec -it some-pod -- curl http://quickcart-api — tests connectivity from within the cluster.

A common real-world issue: you update a Deployment but the selector labels do not match. You wonder why the Service shows no endpoints. You run kubectl get pods --show-labels and compare them to the YAML selector. Once you fix the labels, the endpoint list populates immediately.

How CKAD Actually Tests This

The CKAD exam objectives explicitly require you to 'Create and configure Services to expose applications'. Expect to be tested on these exact areas:

Creating a Service from a YAML manifest or using kubectl expose. You must know the structure of a Service YAML: apiVersion, kind, metadata, spec (type, selector, ports). The kubectl expose command can generate a Service automatically from an existing Deployment.

Choosing the correct Service type for a given scenario. A typical question: 'Expose this Deployment internally only' means ClusterIP. 'Expose for external access in a development environment' means NodePort. 'Expose for production external access' means LoadBalancer.

Understanding the relationship between port, targetPort, and nodePort. You must map them correctly. A common question gives you a Pod listening on port 5000 and asks for a Service that exposes it on port 80.

Troubleshooting connectivity: The exam loves questions where a Service is not working. You need to identify that the selector labels do not match the Pod labels. Another trap: the targetPort is incorrect (e.g., pointing to port 80 on the Pod when the container listens on 8080).

Knowing that kubectl get endpoints is the definitive way to see if the Service has healthy Pods behind it. If endpoints are empty, the selector is wrong, Pods are not running, or readiness probes are failing.

The concept of headless Services: when you set clusterIP: None, DNS queries return all Pod IPs instead of a single virtual IP. Use this for stateful applications that need direct Pod-to-Pod communication (like a database cluster).

The trap with port naming: If you name a port (e.g., port: http), you must reference that name in other resources. The exam may test this in the context of a mult-port Service.

Session affinity: set sessionAffinity: ClientIP. The exam rarely asks for it directly but may mention 'sticky sessions' in a question.

The difference between a Service and an Ingress: Services handle Layer 4 (TCP/UDP) traffic. Ingress handles Layer 7 (HTTP/HTTPS) traffic with routing rules. The exam objective 6.1 specifically excludes Ingress (that is objective 6.2). Do not confuse them.

The default Service type is ClusterIP. If you omit the type field, Kubernetes assumes ClusterIP.

Resource quotas and network policies: The exam may combine Services with NetworkPolicy to restrict traffic. You need to know that a Service itself does not block traffic; you need a separate NetworkPolicy resource.

Trap patterns to watch for:

The question says 'external users must access the application.' You might think LoadBalancer, but if the cluster is on-premise without a cloud load balancer, NodePort is the correct answer. The exam usually gives a cloud context but check carefully.

The question says 'expose the application on port 30000.' That is a NodePort value. The trap is that NodePort range is 30000-32767, but you can also specify a custom port inside that range.

They give a Service YAML with no selector and ask you to debug. A Service without a selector will be missing endpoints. You must manually create an Endpoints object. This is rare but testable.

They ask you to 'update a Service' and you need to edit the YAML and reapply (kubectl apply) or use kubectl edit. You cannot change the clusterIP or type of an existing Service without deleting and recreating it (type can be changed except when going from ExternalName to others).

Key Takeaways

A Service provides a stable virtual IP and DNS name that never changes, even when Pods die and are recreated with new IPs.

The three main Service types are ClusterIP (internal only), NodePort (external via node IP + port), and LoadBalancer (external via cloud load balancer).

The selector field in the Service YAML must exactly match the labels on the Pods you want to target; a mismatch is the most common reason for a broken Service.

kubectl get endpoints shows the actual Pod IP addresses that the Service is currently routing traffic to.

When a Service is defined without a selector, you must manually create an Endpoints object for traffic to flow.

Services use kube-proxy to forward traffic to Pods using default round-robin load balancing, requiring no extra configuration.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

ClusterIP

Reachable only from within the cluster

No external port or IP

Default type if none specified

NodePort

Reachable from outside via any node IP and a port

Uses port range 30000-32767

Builds on top of ClusterIP

NodePort

Exposes on each node's IP

Requires client to know a node IP

No cloud resource provisioning

LoadBalancer

Provisions an external cloud load balancer

Provides a single external IP

Automatically routes to NodePorts

Service

Operates at Layer 4 (TCP/UDP)

Round-robin load balancing only

No URL path routing

Ingress

Operates at Layer 7 (HTTP/HTTPS)

Supports path and host-based routing

Often sits in front of Services

port

Port the Service listens on

What clients connect to

Often set to 80 for HTTP

targetPort

Port on the Pod container

Must match the container's listening port

Often set to 8080 for apps

Watch Out for These

Mistake

A Service directly runs on each Pod like a sidecar.

Correct

A Service is a cluster-level resource managed by the control plane. It does not run inside Pods. It purely exists as a set of rules in kube-proxy and etcd.

People think every Pod needs a 'Service agent' because they imagine a load balancer as software running alongside the app. In reality, kube-proxy on each node handles the forwarding transparently.

Mistake

Creating a Service with type: LoadBalancer immediately gives you a permanent IP that never changes.

Correct

The external IP is provisioned by your cloud provider and may change if you delete and recreate the Service. For a stable IP, you need a static IP reservation from your cloud provider and reference it in the Service spec.

New users see the EXTERNAL-IP field populate and assume it is as static as a DNS record. They do not realise the cloud load balancer resource is ephemeral and tied to the Service lifecycle.

Mistake

Port and targetPort must be the same number.

Correct

They can be different. port is the port the Service listens on (what clients connect to). targetPort is the port on the Pod container. A common pattern is port: 80 and targetPort: 8080.

This comes from a misunderstanding of port forwarding in Docker, where you often map host port to container port 1:1. In Kubernetes, the Service abstracts the mapping.

Mistake

If you set type: ClusterIP, the Service is completely unreachable from outside the cluster, even with kubectl proxy or port-forward.

Correct

ClusterIP Services are not directly routable from outside, but you can still reach them using kubectl port-forward or by running a temporary Pod that proxies traffic. They are not sealed off absolutely.

The name 'ClusterIP' sounds restrictive, and beginners think it means 'cluster-only with no escape'. But administrative tools like kubectl can bypass the restriction for debugging.

Mistake

Kubernetes Services can load balance HTTP requests based on URL paths.

Correct

Services operate at Layer 4 (TCP/UDP) and cannot inspect HTTP paths. Path-based routing requires an Ingress resource or a custom reverse proxy inside the cluster.

The term 'load balancing' is heavily associated with HTTP load balancers (like Nginx or HAProxy) that understand URLs. Kubernetes Services are simpler and do not parse application-layer data.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

Why is my Service showing no endpoints?

This usually means your Service's selector labels do not match any running Pod's labels. Verify with kubectl get pods --show-labels and compare the labels to the selector in your Service YAML.

What is the difference between NodePort and LoadBalancer?

NodePort exposes the Service on a static port (30000-32767) on every node's IP address. LoadBalancer does everything NodePort does PLUS provisions an external cloud load balancer that automatically routes internet traffic to those NodePorts.

Can I change the type of an existing Service?

Yes, you can edit the Service's spec.type field and reapply. However, changing from ClusterIP to NodePort or LoadBalancer will work, but changing from ExternalName to another type may require deleting and recreating the Service.

What port number should I use for NodePort?

You can let Kubernetes assign a random port (30000-32767) by omitting the nodePort field, or you can specify a custom port within that range. Ports outside 30000-32767 are rejected.

How do I expose multiple ports in one Service?

List multiple port entries under spec.ports, each with a unique name, protocol, port, and targetPort. Example: ports: - name: http, port: 80; - name: https, port: 443.

What does a headless Service (clusterIP: None) do?

It disables load balancing and the virtual IP. When you query the DNS name, you get back all the Pod IPs directly. This is useful for stateful applications like databases that need direct client-to-Pod connections.

Terms Worth Knowing

Keep going

You've finished Services, Service Types, and Load Balancing. Continue through the CKAD study guide to build a complete picture of the exam.

Done with this chapter?