- Stable ClusterIP + DNS: Pod IPs change on restart
- Selector must match Pod labels;
targetPortmust matchcontainerPort - Traffic:
port(Service) →targetPort(Pod)
Service types (inheritance)
ClusterIP → NodePort → LoadBalancer
| Type | Access | Production |
|---|---|---|
| ClusterIP | In-cluster only | Yes (internal) |
| NodePort | Node IP + port 30000–32767 | Dev/test only |
| LoadBalancer | Cloud external IP | Yes (external) |
| ExternalName | DNS alias to external hostname | Config only |
ExternalName
Maps a Service name to an external DNS name — no proxying, no selector:
apiVersion: v1
kind: Service
metadata:
name: my-database
namespace: prod
spec:
type: ExternalName
externalName: db.example.com # resolves to this external hostname
- Pods call
my-database.prod.svc.cluster.local→ DNS resolves todb.example.com - Useful for abstracting external services behind a K8s Service name
- No
selector, noportsneeded; no ClusterIP assigned
Create
kubectl run echoserver --image=echoserver --port=8080 -l app=echoserver --expose
kubectl create service clusterip echoserver --tcp=80:8080
kubectl create service nodeport echoserver --tcp=80:8080
kubectl expose deployment echoserver --port=80 --target-port=8080
spec:
type: ClusterIP # default if omitted
selector:
app: echoserver
ports:
- port: 80
targetPort: 8080
Debug checklist
- Service selector matches Pod labels
kubectl get endpoints: empty = no matching Pods- Pod labels and
targetPortvscontainerPort
kubectl describe svc echoserver # Selector, TargetPort, Endpoints
kubectl get endpoints echoserver
kubectl get svc echoserver -o jsonpath='{.spec.selector}'
kubectl get pod --show-labels
Selector mismatch pattern
Empty Endpoints almost always means selector/labels do not match in the same namespace:
kubectl get svc backend -o jsonpath='{.spec.selector}'
kubectl get pod --show-labels
kubectl get endpoints backend
# Fix by editing Service selector or relabeling Pods
kubectl edit svc backend
kubectl label pod <pod> app=api --overwrite
Recreate is sometimes faster on the exam:
kubectl delete svc backend
kubectl expose deployment api --port=80 --target-port=8080 --name=backend
Failures
| Symptom | Cause |
|---|---|
| No endpoints | Selector / label mismatch |
| No traffic | Wrong port / targetPort |
DNS (CoreDNS)
- Same NS:
echoserver - Cross NS:
echoserver.default - FQDN:
echoserver.default.svc.cluster.local
Env vars (kubelet-injected)
<SERVICE>_SERVICE_HOST,<SERVICE>_SERVICE_PORT- Service must exist before Pod creation
NodePort access
kubectl get nodes -o jsonpath='{$.items[*].status.addresses[?(@.type=="InternalIP")].address}'
# wget <node-ip>:<nodePort>
Exam tips
--exposecreates Pod + ClusterIP Service fastest- NodePort: let K8s auto-assign
nodePortunless question specifies - LoadBalancer
EXTERNAL-IPmay show<pending>while provisioning - ExternalName has no selector and no ClusterIP: DNS alias only
- Services select Pods only in the same namespace
- Selector and label values are exact strings:
webdoes not matchwebapp