Services and Networking

Services provide stable network endpoints for accessing Pods. Let’s explore how to expose your applications.

Why Services?

Pods are ephemeral and their IP addresses change. Services solve this by:

  • Providing stable IP addresses and DNS names
  • Load balancing traffic across Pods
  • Enabling service discovery
  • Supporting multiple protocols

Service Types

ClusterIP (Default)

Exposes Service only within the cluster:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080

NodePort

Exposes Service on each Node’s IP at a static port:

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30080 # Optional: 30000-32767

Access via: <NodeIP>:30080

LoadBalancer

Creates external load balancer (cloud providers):

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080

ExternalName

Maps Service to DNS name:

apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: database.example.com

Creating Services

Deploy an application and expose it:

Terminal window
# Create Deployment
kubectl create deployment nginx --image=nginx
# Expose as ClusterIP
kubectl expose deployment nginx --port=80 --target-port=80
# Expose as NodePort
kubectl expose deployment nginx --type=NodePort --port=80
# Expose as LoadBalancer
kubectl expose deployment nginx --type=LoadBalancer --port=80

Service Discovery

DNS

Kubernetes DNS automatically creates records:

Terminal window
# Within same namespace
curl http://my-service
# Across namespaces
curl http://my-service.namespace.svc.cluster.local

Environment Variables

Each Pod gets environment variables for Services:

Terminal window
MY_SERVICE_SERVICE_HOST=10.96.0.10
MY_SERVICE_SERVICE_PORT=80

Endpoints

Services track Pod IPs through Endpoints:

Terminal window
# View Service endpoints
kubectl get endpoints my-service
# Describe Service
kubectl describe service my-service

Session Affinity

Stick clients to same Pod:

spec:
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800

Headless Services

For direct Pod access (StatefulSets):

apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None
selector:
app: my-app
ports:
- port: 80

Multi-Port Services

Support multiple ports:

spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: https
protocol: TCP
port: 443
targetPort: 8443

Testing Services

Terminal window
# Get Service details
kubectl get services
kubectl describe service my-service
# Test from within cluster
kubectl run test --image=busybox -it --rm -- wget -O- http://my-service
# Port forward for local access
kubectl port-forward service/my-service 8080:80
# For NodePort service on Minikube
minikube service my-service
# Get LoadBalancer external IP
kubectl get service my-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Ingress

For HTTP/HTTPS routing with path-based rules:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80

Network Policies

Control traffic between Pods:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080

Best Practices

  1. Use meaningful names - Make Services discoverable
  2. Add labels - Organize and filter Services
  3. Set resource limits - On backing Pods
  4. Use health checks - Ensure traffic goes to healthy Pods
  5. Choose right Service type - Based on access requirements
  6. Implement Network Policies - Secure Pod-to-Pod communication
  7. Monitor Services - Track request rates and errors

Troubleshooting

Common issues:

Terminal window
# Service not accessible
kubectl get endpoints my-service # Check if Pods are selected
kubectl describe service my-service
# DNS not working
kubectl run test --image=busybox -it --rm -- nslookup my-service
kubectl get pods -n kube-system -l k8s-app=kube-dns
# NodePort not accessible
kubectl get nodes -o wide # Get Node IPs
kubectl get service my-service # Verify NodePort
# LoadBalancer pending
kubectl describe service my-service # Check events

Cleanup

Terminal window
# Delete Service
kubectl delete service my-service
# Delete Service and Deployment
kubectl delete deployment,service my-app

Next Steps

You’ve learned how to expose applications with Services. Next, we’ll explore persistent storage with Volumes and PersistentVolumes.