Services & Networking
Pod IPs are ephemeral, so Services provide stable virtual IPs and DNS for a set of pods. Understand ClusterIP, NodePort, LoadBalancer, headless services, selectors and how kube-proxy forwards traffic.
What is this?
A Service is a stable virtual IP (and DNS name) in front of a set of pods selected by labels. Because pod IPs are ephemeral, Services decouple clients from the pods behind them and load-balance traffic across the current endpoints. The default ClusterIP type is cluster-internal only; NodePort and LoadBalancer expose the service beyond the cluster.
Why do you need it?
- Pods come and go; a Service name and IP remain stable across pod churn.
- Label selectors mean the Service automatically tracks the current healthy endpoints.
- Cluster DNS resolves service names, so applications connect by name, not by IP.
- NodePort and LoadBalancer expose services to the outside world in a uniform way.
Mental model
A hotel front desk
A Kubernetes Service
Guests ask for a room by name at the front desk instead of hunting for a specific room number that may change. The desk keeps a list of rooms (endpoints) and sends you to a free one.
How it works
- A Service defines a selector, a port and a targetPort, plus its type.
- The endpoints controller collects the IPs of all pods whose labels match the selector.
- kube-proxy installs rules (iptables or IPVS) that route traffic from the Service ClusterIP to those pod IPs.
- Cluster DNS resolves <service>.<namespace>.svc.cluster.local to the Service IP.
- A headless Service (clusterIP: None) skips the virtual IP so DNS returns pod IPs directly.
Traffic flow from a client through a Service to pod endpoints.
Key commands
kubectl expose deployment nginx --port=80 --target-port=80Create a ClusterIP Service for the deployment's pods.
kubectl get svcList Services with type, cluster IP and ports.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6m nginx ClusterIP 10.96.99.5 <none> 80/TCP 2m
kubectl get endpoints nginxShow the pod IPs currently behind the Service.
kubectl expose deployment nginx --name=nginx-nodeport --type=NodePort --port=80 --target-port=80Expose the Service on every node in the 30000-32767 port range.
kubectl port-forward svc/nginx 8080:80Tunnel a local port to the Service for debugging.
kubectl get svc nginx -o yamlInspect the Service spec including selector and ports.
Examples
Expose a Deployment with a ClusterIP Service
apiVersion: v1kind: Servicemetadata: name: nginxspec: type: ClusterIP selector: app: nginx ports: - port: 80 targetPort: 80The Service matches pods with the label app: nginx and maps its port 80 to their port 80. From anywhere in the cluster, nginx.default.svc.cluster.local resolves to the Service IP, which load-balances across all matching pod endpoints.
In production
- ClusterIP services give microservices stable internal DNS and load balancing.
- NodePort is used for quick external access or as the front door for an Ingress controller on bare metal.
- LoadBalancer services hand off to a cloud load balancer (AWS ELB, GCP LB, Azure LB).
- Headless services back stateful workloads such as databases that need per-pod DNS.
Best practices
- Use precise label selectors so the Service never captures the wrong pods.
- Set explicit targetPort; relying on defaults breaks when pod container ports change.
- Keep databases on ClusterIP only and never expose them via NodePort or LoadBalancer.
- Check kubectl get endpoints after every Service change to confirm pod discovery.
Common mistakes
- Typo in the selector so the Service has no endpoints and returns connection refused.
- Forgetting that targetPort defaults to port, which breaks when the container listens elsewhere.
- Assuming ClusterIP is reachable from outside the cluster.
- Using NodePort range ports (30000-32767) outside the valid range.
Common issues
No endpoints for the ServiceThe label selector matches no pods, or the pods are not Ready.
Run kubectl get pods --show-labels, align the selector to the actual labels, and check readiness.
Connection refused on the ClusterIPtargetPort does not match the port the container listens on.
Verify kubectl get endpoints and the container's listening port, then set the correct targetPort.
LoadBalancer EXTERNAL-IP pending foreverNo cloud load balancer integration on this platform (bare metal or minikube).
Use a NodePort Service, install MetalLB, or run on a cloud provider that provisions the balancer.
Debugging tips
- kubectl get endpoints <svc> tells you if the selector matched any pods.
- kubectl get pods --show-labels lets you compare pod labels with the selector.
- kubectl describe svc <name> shows events and the endpoint count.
- kubectl exec into a pod and nslookup <svc> to verify DNS resolution.
Interview checkpoint
Hands-on lab
- Create a Deployment and a ClusterIP Service
- Verify Endpoints and DNS from another pod
- Expose the Service as a NodePort
- Reach the Service from outside the cluster
Expose a Workload with Services
35 min ยท intermediate
Quick quiz
What is the default Service type?
A Service selects Pods using label selectors.
What is the DNS name for a Service named api in the prod namespace?
Cheat sheet
kubectl expose deploy nginx --port=80 --target-port=80Create ClusterIP Servicekubectl get svcList Serviceskubectl get endpoints nginxBackend pod IPskubectl get svc nginx -o yamlInspect Service speckubectl port-forward svc/nginx 8080:80Local tunnel to Servicekubectl describe svc nginxSelector, ports, events