Services and Networking
Last verified against its sources on 23 September 2026
Services and Networking closes out the CKAD exam at 20%: giving a set of Pods a stable address, routing HTTP traffic to the right one by host and path, and restricting which traffic is allowed at all.
The throughline across all three lessons is the same: a Kubernetes networking object is a declaration of intent, and something else has to actually be running — kube-proxy, an Ingress Controller, a CNI plugin — to turn that declaration into real traffic behavior.
Exposing Applications with Services
- Choose the right Service type — ClusterIP, NodePort, LoadBalancer or headless — for how an application needs to be reached.
- Troubleshoot a Service that isn't routing traffic to its Pods.
A Service gives a stable virtual IP and DNS name to a set
of Pods selected by label, so clients never track individual
Pod addresses that change on every restart or reschedule. The
control plane watches for Pods matching a Service's
spec.selector and records them — as of Kubernetes v1.33, the
classic v1 Endpoints object is officially deprecated in
favor of discovery.k8s.io/v1 EndpointSlice, stable since
v1.21; the API server now warns on kubectl get endpoints.
Four Service types build on each other. ClusterIP, the
default, is reachable only inside the cluster. NodePort
builds on ClusterIP by additionally opening the same port on
every node. LoadBalancer builds on NodePort by provisioning
an external cloud load balancer in front of it. ExternalName
is different in kind — no selector, no proxying, just a DNS
CNAME alias to an external name.
bash
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080A headless Service (clusterIP: None) skips the shared
virtual IP entirely: DNS returns each matching Pod's own IP
individually instead of one load-balanced address — the fit
when clients need to reach a specific replica directly, such
as one member of a StatefulSet, rather than whichever Pod a
Service happens to route to.
When a Service routes to nothing, the most common cause is a
selector that no longer matches any Pod's labels — a typo, or
a label that changed on one side without the other.
kubectl get endpointslices (or the deprecated kubectl get endpoints) for that Service shows the mismatch directly:
zero entries despite Pods visibly Running.
A Service shows zero endpoints even though its Pods are Running. What's the most common cause?Answer it yourself first, then open this.
The Service's selector doesn't match the Pods' current labels — check both sides for a typo or a recent label change.
Routing Traffic with Ingress
- Write Ingress rules that route HTTP traffic by host and path to the correct Service.
- Explain why an Ingress resource does nothing on its own without a controller.
An Ingress (networking.k8s.io/v1) describes HTTP(S)
routing rules — host and path combinations mapped to backend
Services — but on its own it's just data, the same way a CRD
is inert without a controller. Nothing in the core API server
actually routes traffic for it. An Ingress Controller
(nginx, and many others) has to be running in the cluster,
watching Ingress objects and provisioning the real reverse
proxy or load balancer that does the routing. An
IngressClass names which controller a given Ingress
should be handled by.
bash
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: storefront
port:
number: 80pathType has three values, since Kubernetes v1.18.
Prefix matches a path segment by segment. Exact matches
the request path exactly, case-sensitively, with nothing
appended. ImplementationSpecific is the default if
pathType is left unset — its actual matching behavior
depends entirely on whichever controller is running, not on
a fixed Kubernetes-wide rule.
One Ingress, behind one controller, can route many different
hostnames and paths to many different backend Services — the
usual reason to use Ingress at all instead of a separate
LoadBalancer Service per application. A tls section can
also list which Secret holds the certificate for a given
host, so the controller terminates HTTPS at the edge before
forwarding plain HTTP internally, and a defaultBackend can
catch any request that matches none of the declared rules.
An Ingress object is created, but no Ingress Controller is running in the cluster. Does traffic get routed?Answer it yourself first, then open this.
No — an Ingress only supplies routing rules; without a running controller to read and act on them, nothing actually routes traffic.
Restricting Traffic with NetworkPolicies
- Write a NetworkPolicy that restricts a Pod's traffic to only what's explicitly allowed.
- Explain why a NetworkPolicy might have no effect at all in some clusters.
A NetworkPolicy (networking.k8s.io/v1) describes
allowed traffic to and from Pods matched by a podSelector.
But Kubernetes itself does not enforce it — that's the job of
the cluster's CNI network plugin. If the CNI in use
doesn't implement NetworkPolicy, every NetworkPolicy object
in the cluster is accepted and stored, but silently has no
effect at all; traffic keeps flowing as if none existed.
The other default worth knowing: a Pod that no NetworkPolicy selects at all is fully open — Kubernetes' baseline is allow-all, not deny-all, until some policy specifically targets that Pod.
bash
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
spec:
podSelector: {}
policyTypes: ["Ingress"]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
spec:
podSelector:
matchLabels:
app: api
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
role: frontendpolicyTypes (Ingress, Egress, or both) decides which
directions a policy actually restricts for the Pods it
selects. Once any NetworkPolicy selects a Pod for a given
direction, that direction becomes default-deny for that
Pod — only traffic matching an allow rule in some applicable
policy gets through. Multiple policies selecting the same Pod
are additive: the union of everything they each allow,
never a stricter intersection. An ingress[].from entry can
match by podSelector, by namespaceSelector to allow an
entire namespace, or by ipBlock for a CIDR range outside
the cluster; egress rules use the same building blocks in
the outbound direction, including reaching external IPs.
A policy selects Pod X with policyTypes Ingress and an empty ingress list (no rules at all). What happens to incoming traffic to Pod X?Answer it yourself first, then open this.
All of it is denied — selecting a Pod for Ingress with zero allow rules means nothing is permitted in that direction.