Lab 14 - Services
Lab 14 - Services
Goal: reach Pods by a stable name, from inside and from outside. Chapter: Services
# 1 - something to expose
cd ~
kubectl create deploy web --image nginx:1.27 --replicas 3
kubectl get pods -l app=web -o wide # note the Pod IPs
# 2 - ClusterIP, the default
kubectl expose deploy web --port 80 --name web-svc
kubectl get svc web-svc
kubectl get endpointslices -l kubernetes.io/service-name=web-svc
The EndpointSlice is the interesting object: it holds the three Pod IPs. The Service is just a stable front; the EndpointSlice is the live membership list, maintained by a controller as Pods become ready.
# 3 - reach it by name from inside the cluster
kubectl run tmp --image busybox --restart=Never -it --rm -- \
wget -qO- --timeout=3 web-svc | head -3
# 4 - what DNS actually returns
kubectl run tmp --image busybox --restart=Never -it --rm -- \
nslookup web-svc.default.svc.cluster.local
The name resolves to the ClusterIP, not to a Pod. Traffic to that virtual IP is rewritten by kube-proxy on the node to one of the real Pod IPs.
# 5 - stability: destroy every Pod, keep the address
kubectl get svc web-svc -o jsonpath='{.spec.clusterIP}{"\n"}'
kubectl delete pod -l app=web
kubectl get pods -l app=web -o wide # all new IPs
kubectl get svc web-svc -o jsonpath='{.spec.clusterIP}{"\n"}' # unchanged
kubectl get endpointslices -l kubernetes.io/service-name=web-svc # new IPs inside
That is the whole value proposition: the Pods are cattle, the Service name is not.
From outside the cluster
# 6 - NodePort opens the same port on EVERY node
kubectl delete svc web-svc
kubectl expose deploy web --port 80 --type NodePort --name web-svc
PORT=$(kubectl get svc web-svc -o jsonpath='{.spec.ports[0].nodePort}')
echo $PORT
for n in control01 worker01 worker02 worker03; do
echo -n "$n: "; curl -s --max-time 3 http://$n:$PORT | grep -o '<title>.*</title>'
done
Every node answers, including nodes running none of the Pods - kube-proxy forwards for the whole cluster. Note how quickly this gets unmanageable with more than a couple of applications, which is the argument for the Gateway API in the next lab.
# 7 - port-forward, for debugging only
kubectl port-forward svc/web-svc 8080:80 &
curl -s localhost:8080 | head -3
kill %1
port-forward runs on your workstation and dies with the terminal. Useful for
poking at something that has no external access; never part of a solution.
Clean up
# 8 -
kubectl delete svc web-svc
kubectl delete deploy web