Kubernetes Services¶
Services provide stable network endpoints for accessing pods.
Service Overview¶
A Service is an abstraction that defines a logical set of Pods and a policy to access them.
┌────────────────────────────────────────────────┐
│ SERVICE │
│ (ClusterIP: 10.96.0.1) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Load Balancer │ │
│ └──────────┬───────────┬───────────────────┘ │
└─────────────┼───────────┼──────────────────────┘
│ │
┌────────▼──┐ ┌────▼────────┐ ┌──────────┐
│ Pod 1 │ │ Pod 2 │ │ Pod 3 │
│ 10.1.1.1 │ │ 10.1.1.2 │ │ 10.1.1.3 │
│ app=web │ │ app=web │ │ app=web │
└───────────┘ └─────────────┘ └──────────┘
Service Types¶
1. ClusterIP (Default)¶
Exposes service on cluster-internal IP.
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend
ports:
- protocol: TCP
port: 80 # Service port
targetPort: 8080 # Container port
Characteristics:
- Only accessible within cluster
- Default service type
- Gets a stable ClusterIP
- DNS name: <service-name>.<namespace>.svc.cluster.local
2. NodePort¶
Exposes service on each node's IP at a static port.
apiVersion: v1
kind: Service
metadata:
name: nodeport-service
spec:
type: NodePort
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30080 # Optional: 30000-32767
Access Pattern:
3. LoadBalancer¶
Exposes service externally using cloud provider's load balancer.
apiVersion: v1
kind: Service
metadata:
name: loadbalancer-service
spec:
type: LoadBalancer
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
loadBalancerIP: 203.0.113.10 # Optional
Cloud Provider Integration:
External Client
│
▼
Cloud Load Balancer (External IP)
│
▼
NodePort (on all nodes)
│
▼
Service (ClusterIP)
│
▼
Pods
# Get external IP
kubectl get service loadbalancer-service
# Access service
curl http://<external-ip>
4. ExternalName¶
Maps service to external DNS name.
apiVersion: v1
kind: Service
metadata:
name: external-database
spec:
type: ExternalName
externalName: database.example.com
Use Case:
# Application connects to service
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp
env:
- name: DB_HOST
value: external-database.default.svc.cluster.local
Service Definition¶
Complete Service Example¶
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
labels:
app: myapp
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
selector:
app: myapp
tier: frontend
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
externalTrafficPolicy: Local
healthCheckNodePort: 30000
Service Discovery¶
DNS-Based Discovery¶
# Service in same namespace
http://my-service
# Service in different namespace
http://my-service.other-namespace
# Fully qualified
http://my-service.other-namespace.svc.cluster.local
Environment Variables¶
Kubernetes automatically creates environment variables:
# For service named "redis-master"
REDIS_MASTER_SERVICE_HOST=10.96.0.1
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.96.0.1:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.96.0.1:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.96.0.1
Endpoints¶
Services route traffic to endpoints (pod IPs).
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.1.1.1
- ip: 10.1.1.2
ports:
- port: 8080
# View endpoints
kubectl get endpoints my-service
# Describe endpoints
kubectl describe endpoints my-service
EndpointSlices¶
More scalable alternative to Endpoints:
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-abc
labels:
kubernetes.io/service-name: my-service
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 8080
endpoints:
- addresses:
- "10.1.1.1"
conditions:
ready: true
hostname: pod-1
nodeName: node-1
Headless Services¶
Service without ClusterIP for direct pod access.
apiVersion: v1
kind: Service
metadata:
name: headless-service
spec:
clusterIP: None # Headless
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
DNS Returns: - Pod IPs directly (not service IP) - Useful for StatefulSets - Client-side load balancing
Service Without Selector¶
For external services or custom endpoints:
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-service
subsets:
- addresses:
- ip: 192.168.1.100
- ip: 192.168.1.101
ports:
- port: 80
Multi-Port Services¶
apiVersion: v1
kind: Service
metadata:
name: multi-port-service
spec:
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443
- name: metrics
protocol: TCP
port: 9090
targetPort: 9090
Session Affinity¶
Route requests from same client to same pod:
apiVersion: v1
kind: Service
metadata:
name: sticky-service
spec:
selector:
app: myapp
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800 # 3 hours
ports:
- port: 80
targetPort: 8080
Options: - None: Default, random distribution - ClientIP: Based on client IP
External Traffic Policy¶
Control how external traffic is routed:
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: LoadBalancer
externalTrafficPolicy: Local # or Cluster (default)
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
Cluster (Default): - Traffic distributed to all pods - May involve extra hop - Source IP is masked
Local: - Traffic only to pods on receiving node - Preserves source IP - Better performance - May cause imbalance
Service Topology¶
Route traffic based on topology:
apiVersion: v1
kind: Service
metadata:
name: topology-aware-service
spec:
selector:
app: myapp
ports:
- port: 80
topologyKeys:
- "kubernetes.io/hostname"
- "topology.kubernetes.io/zone"
- "*"
Service Annotations¶
AWS Load Balancer¶
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-internal: "true"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:..."
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
GCP Load Balancer¶
metadata:
annotations:
cloud.google.com/load-balancer-type: "Internal"
networking.gke.io/load-balancer-type: "Internal"
Azure Load Balancer¶
metadata:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-load-balancer-internal-subnet: "subnet-name"
Service Commands¶
# Create service
kubectl expose deployment nginx --port=80 --target-port=8080
# Create service from YAML
kubectl apply -f service.yaml
# List services
kubectl get services
kubectl get svc
# Describe service
kubectl describe service my-service
# Get service details
kubectl get service my-service -o yaml
# Get endpoints
kubectl get endpoints my-service
# Delete service
kubectl delete service my-service
# Port forward to service
kubectl port-forward service/my-service 8080:80
# Get service URL (Minikube)
minikube service my-service --url
Service Mesh Integration¶
Istio Service¶
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 75
- destination:
host: reviews
subset: v2
weight: 25
Troubleshooting Services¶
# Check service exists
kubectl get service my-service
# Check endpoints
kubectl get endpoints my-service
# Verify selector matches pods
kubectl get pods -l app=myapp
# Test DNS resolution
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup my-service
# Test connectivity
kubectl run -it --rm debug --image=busybox --restart=Never -- wget -O- http://my-service
# Check kube-proxy logs
kubectl logs -n kube-system -l k8s-app=kube-proxy
# View iptables rules
kubectl exec -n kube-system <kube-proxy-pod> -- iptables-save | grep my-service
Best Practices¶
- Use Appropriate Service Type
- ClusterIP for internal services
- LoadBalancer for external access
-
NodePort for development/testing
-
Health Checks
- Implement readiness probes
- Pods must be ready to receive traffic
-
Unhealthy pods removed from endpoints
-
Resource Naming
- Use descriptive names
- Follow naming conventions
-
Include environment in name
-
Port Naming
- Name ports in multi-port services
-
Use standard names (http, https, metrics)
-
Session Affinity
- Use only when necessary
- Consider stateless design
-
May cause load imbalance
-
External Traffic
- Use Local policy to preserve source IP
- Consider load distribution
- Monitor node-level traffic