A detailed comparison of the four Kubernetes Service types — when to use each, their YAML patterns, and their behavior in different environments. Synthesized from CKA Day 9 — Kubernetes Services Explained.
Quick Comparison
Type
Scope
External Access
Use Case
CKA Relevance
ClusterIP
Internal only
❌ No
Pod-to-Pod communication
Very High
NodePort
External via Node IP
✅ Port 30,000–32,767
Dev, bare metal, no cloud LB
High
LoadBalancer
External via cloud LB
✅ Auto-provisioned IP
Production on cloud providers
Medium
ExternalName
DNS alias
❌ (redirects)
External database/API integration
Low
1. ClusterIP (Default)
ClusterIP is the default Service type. It assigns an internal IP address that is reachable only from within the cluster.
# From another Pod in the same namespacecurl http://backend-svc:8080# Fully Qualified Domain Name (FQDN)curl http://backend-svc.default.svc.cluster.local:8080
Key Characteristics
Most secure — no external exposure
Zero cloud-provider dependency
If type is omitted, Kubernetes assumes ClusterIP
The kubernetes default Service in default namespace is a ClusterIP pointing to the API Server
2. NodePort
NodePort extends ClusterIP by exposing the Service on a static port (30,000–32,767) on every node’s IP address.
When to Use
Local development and testing
Bare-metal clusters without a cloud load balancer
Quick external access when you don’t need a fancy LB
YAML
apiVersion: v1kind: Servicemetadata: name: nginx-nodeportspec: type: NodePort selector: app: nginx ports: - port: 80 targetPort: 80 nodePort: 30001 # Must be in range 30000-32767
Access Patterns
# From outside the cluster (any node IP)curl http://<NodeIP>:30001# Check which node a Pod runs onkubectl get pods -o widekubectl describe pod <pod-name> | grep Node:
Internal Behavior
Even with NodePort, the Service still creates a ClusterIP internally. The flow is:
Then recreate the cluster. On cloud VMs, bare metal, or the CKA exam, this extra step is unnecessary. Source: CKA Day 9
3. LoadBalancer
LoadBalancer extends NodePort by provisioning an external cloud load balancer. It provides a single public IP or DNS name that distributes traffic across all nodes.
When to Use
Production workloads on AWS, Azure, GCP, or any cloud with LB integration
When you need a stable public endpoint (myapp.com)
When you want the cloud provider to handle health checks and traffic distribution
# From inside the cluster, this resolves to database.example.comcurl http://external-db# DNS lookupnslookup external-db.default.svc.cluster.local# Server: database.example.com
Key Characteristics
No selector — it doesn’t select Pods
No ports section needed
No ClusterIP assigned
Pure DNS redirection; the actual connection is made to the external domain
If the external domain changes, update the Service — application code stays unchanged
Selector Behavior Across Types
Service Type
Requires Selector?
Selects Pods?
Creates Endpoints?
ClusterIP
Yes
Yes
Yes
NodePort
Yes
Yes
Yes
LoadBalancer
Yes
Yes
Yes
ExternalName
No
No
No
Choosing the Right Service Type
Is the traffic internal only?
├── YES → ClusterIP
└── NO → Is this a cloud production environment?
├── YES → LoadBalancer
└── NO → Do you need external access?
├── YES → NodePort
└── NO → ExternalName (external DNS alias)
Exam Traps & Common Mistakes
Case Sensitivity:NodePort and LoadBalancer must use capital N/P and L/B. nodeport or loadbalancer will be rejected.
Selector vs matchLabels: Services use selector: {app: nginx}, NOT selector: matchLabels: {app: nginx}. The latter is for Deployments/ReplicaSets.
NodePort Range: Manually specified nodePort must be 30,000–32,767. Values outside this range are rejected.
Kind Port Mapping: Forgetting extraPortMappings in Kind and wondering why NodePort doesn’t work from localhost.
LoadBalancer on Local: Expecting an external IP on Kind/minikube without a cloud provider or MetalLB.
Ingress as the Alternative: For multiple HTTP apps, using one LoadBalancer per Service is wasteful. Use a single LoadBalancer for the Ingress Controller, then route all apps via Ingress rules.
Exam-style hands-on tasks for this topic. Complete each task before reviewing the solution. Time yourself — CKA tasks average 5–7 minutes.
Task 1: Convert ClusterIP to NodePort
You are asked to convert the existing ClusterIP Service backend-svc to type NodePort without changing its selector or ports.
Requirements: Preserve the existing port configuration; allocate a NodePort automatically.
Verification:kubectl get svc backend-svc shows TYPE as NodePort.
Solution:
kubectl patch svc backend-svc --type='json' -p='[{"op": "replace", "path": "/spec/type", "value":"NodePort"}]'# Or edit and re-apply the modified YAML
Task 2: Create a LoadBalancer Service
You are asked to create a Service named api-lb of type LoadBalancer targeting Pods with label app=api on port 80.
Requirements: Use imperative generation.
Verification:kubectl get svc api-lbSolution:
kubectl create service loadbalancer api-lb --tcp=80:80 --dry-run=client -o yaml > api-lb.yaml# Edit api-lb.yaml to add `selector: { app: api }` under spec, then applykubectl apply -f api-lb.yaml
Task 3: Create an ExternalName Service
You are asked to create an ExternalName Service external-db pointing to my.database.example.com.
Requirements: No selector or ports section should exist.
Verification:kubectl get svc external-db and kubectl describe svc external-dbSolution: