13 KiB
Kubernetes Service Specification Reference
Comprehensive reference for Kubernetes Service resources, covering service types, networking, load balancing, and service discovery patterns.
Overview
A Service provides stable network endpoints for accessing Pods. Services enable loose coupling between microservices by providing service discovery and load balancing.
Service Types
1. ClusterIP (Default)
Exposes the service on an internal cluster IP. Only reachable from within the cluster.
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: production
spec:
type: ClusterIP
selector:
app: backend
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
sessionAffinity: None
Use cases:
- Internal microservice communication
- Database services
- Internal APIs
- Message queues
2. NodePort
Exposes the service on each Node's IP at a static port (30000-32767 range).
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30080 # Optional, auto-assigned if omitted
protocol: TCP
Use cases:
- Development/testing external access
- Small deployments without load balancer
- Direct node access requirements
Limitations:
- Limited port range (30000-32767)
- Must handle node failures
- No built-in load balancing across nodes
3. LoadBalancer
Exposes the service using a cloud provider's load balancer.
apiVersion: v1
kind: Service
metadata:
name: public-api
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: api
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP
loadBalancerSourceRanges:
- 203.0.113.0/24
Cloud-specific annotations:
AWS:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb" # or "external"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:..."
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
Azure:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
service.beta.kubernetes.io/azure-pip-name: "my-public-ip"
GCP:
annotations:
cloud.google.com/load-balancer-type: "Internal"
cloud.google.com/backend-config: '{"default": "my-backend-config"}'
4. ExternalName
Maps service to external DNS name (CNAME record).
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.external.example.com
ports:
- port: 5432
Use cases:
- Accessing external services
- Service migration scenarios
- Multi-cluster service references
Complete Service Specification
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: production
labels:
app: my-app
tier: backend
annotations:
description: "Main application service"
prometheus.io/scrape: "true"
spec:
# Service type
type: ClusterIP
# Pod selector
selector:
app: my-app
version: v1
# Ports configuration
ports:
- name: http
port: 80 # Service port
targetPort: 8080 # Container port (or named port)
protocol: TCP # TCP, UDP, or SCTP
# Session affinity
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
# IP configuration
clusterIP: 10.0.0.10 # Optional: specific IP
clusterIPs:
- 10.0.0.10
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
# External traffic policy
externalTrafficPolicy: Local
# Internal traffic policy
internalTrafficPolicy: Local
# Health check
healthCheckNodePort: 30000
# Load balancer config (for type: LoadBalancer)
loadBalancerIP: 203.0.113.100
loadBalancerSourceRanges:
- 203.0.113.0/24
# External IPs
externalIPs:
- 80.11.12.10
# Publishing strategy
publishNotReadyAddresses: false
Port Configuration
Named Ports
Use named ports in Pods for flexibility:
Deployment:
spec:
template:
spec:
containers:
- name: app
ports:
- name: http
containerPort: 8080
- name: metrics
containerPort: 9090
Service:
spec:
ports:
- name: http
port: 80
targetPort: http # References named port
- name: metrics
port: 9090
targetPort: metrics
Multiple Ports
spec:
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: https
port: 443
targetPort: 8443
protocol: TCP
- name: grpc
port: 9090
targetPort: 9090
protocol: TCP
Session Affinity
None (Default)
Distributes requests randomly across pods.
spec:
sessionAffinity: None
ClientIP
Routes requests from same client IP to same pod.
spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800 # 3 hours
Use cases:
- Stateful applications
- Session-based applications
- WebSocket connections
Traffic Policies
External Traffic Policy
Cluster (Default):
spec:
externalTrafficPolicy: Cluster
- Load balances across all nodes
- May add extra network hop
- Source IP is masked
Local:
spec:
externalTrafficPolicy: Local
- Traffic goes only to pods on receiving node
- Preserves client source IP
- Better performance (no extra hop)
- May cause imbalanced load
Internal Traffic Policy
spec:
internalTrafficPolicy: Local # or Cluster
Controls traffic routing for cluster-internal clients.
Headless Services
Service without cluster IP for direct pod access.
apiVersion: v1
kind: Service
metadata:
name: database
spec:
clusterIP: None # Headless
selector:
app: database
ports:
- port: 5432
targetPort: 5432
Use cases:
- StatefulSet pod discovery
- Direct pod-to-pod communication
- Custom load balancing
- Database clusters
DNS returns:
- Individual pod IPs instead of service IP
- Format:
<pod-name>.<service-name>.<namespace>.svc.cluster.local
Service Discovery
DNS
ClusterIP Service:
<service-name>.<namespace>.svc.cluster.local
Example:
curl http://backend-service.production.svc.cluster.local
Within same namespace:
curl http://backend-service
Headless Service (returns pod IPs):
<pod-name>.<service-name>.<namespace>.svc.cluster.local
Environment Variables
Kubernetes injects service info into pods:
# Service host and port
BACKEND_SERVICE_SERVICE_HOST=10.0.0.100
BACKEND_SERVICE_SERVICE_PORT=80
# For named ports
BACKEND_SERVICE_SERVICE_PORT_HTTP=80
Note: Pods must be created after the service for env vars to be injected.
Load Balancing
Algorithms
Kubernetes uses random selection by default. For advanced load balancing:
Service Mesh (Istio example):
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-destination-rule
spec:
host: my-service
trafficPolicy:
loadBalancer:
simple: LEAST_REQUEST # or ROUND_ROBIN, RANDOM, PASSTHROUGH
connectionPool:
tcp:
maxConnections: 100
Connection Limits
Use pod disruption budgets and resource limits:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app
Service Mesh Integration
Istio Virtual Service
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-service
spec:
hosts:
- my-service
http:
- match:
- headers:
version:
exact: v2
route:
- destination:
host: my-service
subset: v2
- route:
- destination:
host: my-service
subset: v1
weight: 90
- destination:
host: my-service
subset: v2
weight: 10
Common Patterns
Pattern 1: Internal Microservice
apiVersion: v1
kind: Service
metadata:
name: user-service
namespace: backend
labels:
app: user-service
tier: backend
spec:
type: ClusterIP
selector:
app: user-service
ports:
- name: http
port: 8080
targetPort: http
protocol: TCP
- name: grpc
port: 9090
targetPort: grpc
protocol: TCP
Pattern 2: Public API with Load Balancer
apiVersion: v1
kind: Service
metadata:
name: api-gateway
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:..."
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app: api-gateway
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP
loadBalancerSourceRanges:
- 0.0.0.0/0
Pattern 3: StatefulSet with Headless Service
apiVersion: v1
kind: Service
metadata:
name: cassandra
spec:
clusterIP: None
selector:
app: cassandra
ports:
- port: 9042
targetPort: 9042
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: cassandra
spec:
serviceName: cassandra
replicas: 3
selector:
matchLabels:
app: cassandra
template:
metadata:
labels:
app: cassandra
spec:
containers:
- name: cassandra
image: cassandra:4.0
Pattern 4: External Service Mapping
apiVersion: v1
kind: Service
metadata:
name: external-database
spec:
type: ExternalName
externalName: prod-db.cxyz.us-west-2.rds.amazonaws.com
---
# Or with Endpoints for IP-based external service
apiVersion: v1
kind: Service
metadata:
name: external-api
spec:
ports:
- port: 443
targetPort: 443
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: external-api
subsets:
- addresses:
- ip: 203.0.113.100
ports:
- port: 443
Pattern 5: Multi-Port Service with Metrics
apiVersion: v1
kind: Service
metadata:
name: web-app
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
spec:
type: ClusterIP
selector:
app: web-app
ports:
- name: http
port: 80
targetPort: 8080
- name: metrics
port: 9090
targetPort: 9090
Network Policies
Control traffic to services:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Best Practices
Service Configuration
- Use named ports for flexibility
- Set appropriate service type based on exposure needs
- Use labels and selectors consistently across Deployments and Services
- Configure session affinity for stateful apps
- Set external traffic policy to Local for IP preservation
- Use headless services for StatefulSets
- Implement network policies for security
- Add monitoring annotations for observability
Production Checklist
- Service type appropriate for use case
- Selector matches pod labels
- Named ports used for clarity
- Session affinity configured if needed
- Traffic policy set appropriately
- Load balancer annotations configured (if applicable)
- Source IP ranges restricted (for public services)
- Health check configuration validated
- Monitoring annotations added
- Network policies defined
Performance Tuning
For high traffic:
spec:
externalTrafficPolicy: Local
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
For WebSocket/long connections:
spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 86400 # 24 hours
Troubleshooting
Service not accessible
# Check service exists
kubectl get service <service-name>
# Check endpoints (should show pod IPs)
kubectl get endpoints <service-name>
# Describe service
kubectl describe service <service-name>
# Check if pods match selector
kubectl get pods -l app=<app-name>
Common issues:
- Selector doesn't match pod labels
- No pods running (endpoints empty)
- Ports misconfigured
- Network policy blocking traffic
DNS resolution failing
# Test DNS from pod
kubectl run debug --rm -it --image=busybox -- nslookup <service-name>
# Check CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
Load balancer issues
# Check load balancer status
kubectl describe service <service-name>
# Check events
kubectl get events --sort-by='.lastTimestamp'
# Verify cloud provider configuration
kubectl describe node