Kubernetes Services
What Are Services?
A Kubernetes Service provides a stable network interface to pods. Since pods are ephemeral (created and destroyed frequently), Services abstract this instability by providing a fixed DNS name and IP address that routes traffic to current pod replicas.
Why Services matter: Without Services, clients would need to track individual pod IP addresses that change constantly. Services enable reliable inter-pod and external communication regardless of pod lifecycle.
Service Types
graph TD
A["Service Types"] -->B["ClusterIP
Internal Only"]
A -->C["NodePort
External Access
via Node IP"]
A -->D["LoadBalancer
Cloud Load Balancer"]
A -->E["ExternalName
External Service DNS"]
style B fill:#90EE90
style C fill:#FFD700
style D fill:#87CEEB
style E fill:#FFB6C6
ClusterIP (Default)
Exposes Service only within cluster. Internal pods communicate via service DNS.
Why ClusterIP: Most internal services don't need external access. This type is lightweight and secure.
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- port: 80
targetPort: 5000
type: ClusterIP
Usage within cluster:
# From another pod
curl http://api-service/ # Resolves to service IP
NodePort
Exposes Service on each node's IP at a static port. External traffic accesses via NODE_IP:PORT.
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
nodePort: 30080
type: NodePort
Access from outside:
curl http://node-ip:30080
Drawback: Clients must know node IPs and ports change. Better for development/testing.
LoadBalancer
Provisions cloud load balancer (AWS ELB, Azure LB, GCP LB). External traffic routes through load balancer to service.
apiVersion: v1
kind: Service
metadata:
name: api-lb
spec:
selector:
app: api
ports:
- port: 80
targetPort: 5000
type: LoadBalancer
Get external IP:
kubectl get service api-lb
# or shorter: kubectl get svc api-lb
# Shows EXTERNAL-IP assigned by cloud provider
Why LoadBalancer: Production-grade external access with high availability and automatic failover.
ExternalName
Provides internal DNS alias for external service.
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.example.com
Internal pods access external database:
# From inside cluster
curl external-db:5432
Service Discovery
Services are discovered by DNS. Kubernetes maintains internal DNS that resolves service names to IPs.
DNS Name Format
SERVICE_NAME.NAMESPACE.svc.cluster.local
Examples:
# Same namespace
curl http://api-service
# Different namespace
curl http://api-service.production
# Full DNS name
curl http://api-service.production.svc.cluster.local
Load Balancing
Services automatically load balance traffic across pod replicas using round-robin by default.
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
sessionAffinity: ClientIP # Sticky sessions
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
Why load balancing: Distributes traffic evenly, preventing any single pod from becoming bottleneck.
Endpoints
Services dynamically track healthy pods via Endpoints object.
# View endpoints for service
kubectl get endpoints web-service
# or shorter: kubectl get ep web-service
# Shows pod IPs currently receiving traffic
# Automatically updates when pods are added/removed
Headless Services
Services without ClusterIP for situations requiring direct pod access.
apiVersion: v1
kind: Service
metadata:
name: database
spec:
clusterIP: None # Headless
selector:
app: postgres
ports:
- port: 5432
Returns individual pod IPs instead of service IP:
nslookup database
# Returns all pod IPs
When to use: StatefulSets, where each pod's identity matters (databases, cache clusters).
Ingress (External HTTP/HTTPS Routing)
Services handle networking, but Ingress handles HTTP/HTTPS routing based on hostnames and paths.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Why Ingress: Ingress controllers (nginx, traefik) manage HTTP routing, SSL/TLS, and virtual hosts more efficiently than LoadBalancer services.
Real-World Service Mesh Example
# Backend API
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- name: http
port: 80
targetPort: 5000
---
# Frontend Web
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- name: http
port: 80
targetPort: 8080
type: LoadBalancer
---
# Internal Cache
apiVersion: v1
kind: Service
metadata:
name: cache
spec:
selector:
app: redis
ports:
- name: redis
port: 6379
targetPort: 6379
clusterIP: None # Headless for direct pod access
Communication:
- Web pods access API:
http://api(ClusterIP) - Web accessible externally: LoadBalancer routes traffic
- API pods access Cache: Direct pod IPs via
cacheHeadless service
Common Pitfalls
- No service selector - Service has no pods to route to; traffic fails
- Wrong targetPort - Service port doesn't match container port
- Relying on pod IP - Pod IPs change; always use service DNS
- Too many services - Creates management overhead; combine where possible
Key Takeaways
- Services provide stable DNS names and load balancing across ephemeral pods
- ClusterIP (default) for internal communication; LoadBalancer for external access
- Service discovery via DNS enables flexible inter-pod communication
- Services automatically track healthy pods and remove failed pods from traffic
- Headless services support stateful applications where pod identity matters
- Ingress controllers provide HTTP/HTTPS routing for multiple services
- Load balancing distributes traffic evenly across replicas
Next Steps: Create services for existing deployments, configure external access with LoadBalancer or Ingress, test service discovery and failover.