[5/24] S is for Services: Networking and Service Discovery


πŸ“š This is Post #5 in the Kubernetes A-to-Z Series

Reading Order: ← Previous: Deployments β†’ Next: ReplicaSets β†’

Series Progress: 5/24 complete | Difficulty: Intermediate | Time: 20 min | Part 2/6: Core Workloads

Welcome to the fifth post in our Kubernetes A-to-Z Series! Now that you understand Deployments, let’s explore Services - the networking abstraction that enables communication between applications in Kubernetes. Services provide stable network endpoints, load balancing, and service discovery for your containerized applications.

What is a Kubernetes Service?

A Service is an abstraction that defines a logical set of Pods and a policy by which to access them. Services enable loose coupling between microservices and provide stable network endpoints regardless of pod lifecycle changes.

Service vs Deployment

Deployment (Application Management):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Deployment Controller              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  ReplicaSet                 β”‚    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”   β”‚    β”‚
β”‚  β”‚  β”‚Pod1 β”‚ β”‚Pod2 β”‚ β”‚Pod3 β”‚   β”‚    β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜   β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Manages application lifecycle

Service (Network Abstraction):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Service: webapp-service            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Stable IP: 10.96.0.1       β”‚    β”‚
β”‚  β”‚  Port: 80                   β”‚    β”‚
β”‚  β”‚  Load Balancer              β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚           β”‚                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”            β”‚
β”‚  β”‚Pod1 β”‚ β”‚Pod2 β”‚ β”‚Pod3 β”‚            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Provides stable networking

Key Service Features

  • Stable Network Identity: Consistent IP address and DNS name
  • Load Balancing: Distribute traffic across multiple pods
  • Service Discovery: Automatic registration and discovery
  • Loose Coupling: Services abstract pod implementation details
  • Multiple Access Patterns: ClusterIP, NodePort, LoadBalancer

Service Types Explained

1. ClusterIP (Default)

Exposes service on an internal IP address accessible only within the cluster:

# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-clusterip
spec:
  type: ClusterIP
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

2. NodePort

Exposes service on each node’s IP at a static port:

# nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-nodeport
spec:
  type: NodePort
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080  # Optional: specify node port (30000-32767)
    protocol: TCP

3. LoadBalancer

Exposes service externally using a cloud provider’s load balancer:

# loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Creating and Managing Services

Basic Service Creation

# Create service imperatively
kubectl expose deployment webapp-deployment --port=80 --target-port=8080

# Create specific service types
kubectl expose deployment webapp-deployment --port=80 --target-port=8080 --type=NodePort
kubectl expose deployment webapp-deployment --port=80 --target-port=8080 --type=LoadBalancer

# Get services
kubectl get services
kubectl get service webapp-clusterip

# Describe service
kubectl describe service webapp-clusterip

Service with Deployment Example

# complete-example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: myapp:v1.0
        ports:
        - containerPort: 8080
        env:
        - name: SERVICE_NAME
          value: "webapp"
---
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  type: ClusterIP
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
# Apply both resources
kubectl apply -f complete-example.yaml

# Test service connectivity
kubectl run test-pod --image=busybox --rm -it -- /bin/sh
# Inside the pod:
wget -qO- http://webapp-service

Service Discovery Mechanisms

1. Environment Variables

Kubernetes automatically injects service information as environment variables:

# Check environment variables in a pod
kubectl exec -it webapp-deployment-xxxxx -- env | grep WEBAPP

# Expected output:
WEBAPP_SERVICE_HOST=10.96.0.1
WEBAPP_SERVICE_PORT=80

2. DNS Discovery

Services are automatically registered in cluster DNS:

# Test DNS resolution
kubectl run dns-test --image=busybox --rm -it -- /bin/sh

# Inside the pod:
nslookup webapp-service
nslookup webapp-service.default.svc.cluster.local

3. Service Discovery in Action

# service-discovery-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: frontend:v1.0
        ports:
        - containerPort: 3000
        env:
        - name: BACKEND_URL
          value: "http://backend-service:8080"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: backend:v1.0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - port: 8080
    targetPort: 8080
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 3000
    nodePort: 30080
    protocol: TCP

Advanced Service Features

1. Headless Services

For direct pod access without load balancing:

# headless-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-headless
spec:
  clusterIP: None  # This makes it headless
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

2. Services with Session Affinity

For sticky sessions:

# session-affinity-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-sticky
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800  # 3 hours
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

3. ExternalName Services

For external service references:

# externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-database
spec:
  type: ExternalName
  externalName: database.external-service.com

Load Balancing Algorithms

1. Round Robin (Default)

Distributes requests evenly across pods:

# round-robin-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-roundrobin
spec:
  type: ClusterIP
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080

2. Session Affinity

Routes requests from same client to same pod:

# session-affinity-lb.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-affinity
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080

Service Troubleshooting

Common Issues and Solutions

# Check service status
kubectl get services
kubectl get endpoints

# Describe service for details
kubectl describe service webapp-service

# Check if service has endpoints
kubectl get endpoints webapp-service

# Test service connectivity
kubectl run test-pod --image=busybox --rm -it -- /bin/sh
# Inside pod:
wget -qO- http://webapp-service

# Check DNS resolution
kubectl run dns-test --image=busybox --rm -it -- /bin/sh
# Inside pod:
nslookup webapp-service

# Check service events
kubectl get events --field-selector involvedObject.name=webapp-service

Debugging Service Issues

# Check if pods have correct labels
kubectl get pods --show-labels | grep webapp

# Verify service selector matches pod labels
kubectl describe service webapp-service | grep Selector

# Check if pods are ready
kubectl get pods -l app=webapp

# Check pod logs
kubectl logs -l app=webapp --tail=50

# Test direct pod connectivity
kubectl exec -it webapp-pod-xxxx -- wget -qO- localhost:8080

Service Best Practices

1. Naming Conventions

# good-naming-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-backend-service  # Descriptive name
  labels:
    app: webapp
    tier: backend
    environment: production
spec:
  type: ClusterIP
  selector:
    app: webapp
    tier: backend
  ports:
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP

2. Health Checks Integration

# service-with-health-checks.yaml
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  type: ClusterIP
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: myapp:v1.0
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

Service Commands Reference

# Service Management
kubectl create service clusterip webapp --tcp=80:8080
kubectl expose deployment webapp-deployment --port=80 --target-port=8080
kubectl get services
kubectl describe service webapp-service

# Service Types
kubectl expose deployment webapp --port=80 --target-port=8080 --type=NodePort
kubectl expose deployment webapp --port=80 --target-port=8080 --type=LoadBalancer
kubectl expose deployment webapp --port=80 --target-port=8080 --type=ClusterIP

# Service Discovery
kubectl exec -it pod-name -- nslookup webapp-service
kubectl exec -it pod-name -- env | grep WEBAPP
kubectl get endpoints webapp-service

# Port Forwarding (for testing)
kubectl port-forward service/webapp-service 8080:80

# Delete service
kubectl delete service webapp-service

Real-World Service Architecture

Microservices Communication Pattern

# microservices-architecture.yaml
# Frontend Service
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 3000
    nodePort: 30080
---
# API Gateway Service
apiVersion: v1
kind: Service
metadata:
  name: api-gateway-service
spec:
  type: ClusterIP
  selector:
    app: api-gateway
  ports:
  - port: 8080
    targetPort: 8080
---
# User Service
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  type: ClusterIP
  selector:
    app: user-service
  ports:
  - port: 8081
    targetPort: 8081
---
# Database Service (External)
apiVersion: v1
kind: Service
metadata:
  name: database-service
spec:
  type: ExternalName
  externalName: postgres.database.internal

Key Takeaways

  • Services provide stable network endpoints for dynamic pods
  • Service types (ClusterIP, NodePort, LoadBalancer) serve different access patterns
  • Service discovery works via environment variables and DNS
  • Load balancing distributes traffic across healthy pods
  • Health probes ensure only ready pods receive traffic
  • Session affinity can maintain client-to-pod relationships
  • ExternalName services can reference external resources

Command Reference Cheatsheet

# Service Creation and Management
kubectl expose deployment webapp --port=80 --target-port=8080
kubectl expose deployment webapp --port=80 --target-port=8080 --type=NodePort
kubectl expose deployment webapp --port=80 --target-port=8080 --type=LoadBalancer
kubectl get services
kubectl describe service webapp-service

# Service Discovery Testing
kubectl exec -it pod-name -- nslookup webapp-service
kubectl exec -it pod-name -- wget -qO- http://webapp-service
kubectl get endpoints webapp-service

# Port Forwarding for Testing
kubectl port-forward service/webapp-service 8080:80

# Service Troubleshooting
kubectl get events --field-selector involvedObject.name=webapp-service
kubectl describe service webapp-service
kubectl get pods --show-labels | grep webapp

Next Steps

Now that you understand Services and networking in Kubernetes, you’re ready to explore ReplicaSets in the next post. We’ll learn how to ensure high availability and manage pod replicas at scale, completing our coverage of core workloads and management.

Resources for Further Learning


Series Navigation:

Complete Series: Kubernetes A-to-Z Series Overview