Skip to content
Rahul Shishodiaon GitHub LinkedIn profile

Services

  • Stable ClusterIP + DNS: Pod IPs change on restart
  • Selector must match Pod labels; targetPort must match containerPort
  • Traffic: port (Service) → targetPort (Pod)

Service types (inheritance)

ClusterIP → NodePort → LoadBalancer
TypeAccessProduction
ClusterIPIn-cluster onlyYes (internal)
NodePortNode IP + port 30000–32767Dev/test only
LoadBalancerCloud external IPYes (external)
ExternalNameDNS alias to external hostnameConfig 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 to db.example.com
  • Useful for abstracting external services behind a K8s Service name
  • No selector, no ports needed; 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

  1. Service selector matches Pod labels
  2. kubectl get endpoints: empty = no matching Pods
  3. Pod labels and targetPort vs containerPort
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

SymptomCause
No endpointsSelector / label mismatch
No trafficWrong 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

  • --expose creates Pod + ClusterIP Service fastest
  • NodePort: let K8s auto-assign nodePort unless question specifies
  • LoadBalancer EXTERNAL-IP may 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: web does not match webapp