Kubernetes LoadBalancer
Introduction
When deploying applications in Kubernetes, making them accessible outside the cluster is a common requirement. Kubernetes offers several ways to expose your applications, with the LoadBalancer Service type being one of the most powerful options for production environments.
A LoadBalancer Service is a Kubernetes resource that provisions an external load balancer in your cloud environment (like AWS, GCP, or Azure), configures it to send traffic to your Service, and exposes it with an external IP address. This provides a straightforward way to route external traffic to your applications running inside Kubernetes.
How LoadBalancer Services Work
To understand LoadBalancer Services, let's first review the Kubernetes Service types hierarchy:
- ClusterIP (default): Exposes the Service on an internal IP within the cluster
- NodePort: Exposes the Service on each Node's IP at a static port
- LoadBalancer: Exposes the Service externally using a cloud provider's load balancer
- ExternalName: Maps the Service to a DNS name
The LoadBalancer Service type builds on the NodePort Service type. When you create a LoadBalancer Service:
- Kubernetes creates a ClusterIP Service
- It then creates a NodePort Service that routes to the ClusterIP Service
- Finally, it interacts with the cloud provider's API to provision an external load balancer that routes to the NodePort Service
When to Use a LoadBalancer
LoadBalancer Services are ideal when:
- You need a public, stable IP address for your service
- You want built-in load balancing capabilities
- You're running in a cloud environment that supports automatic load balancer provisioning
- You need to expose a service externally in a production environment
Implementing a LoadBalancer Service
Let's look at how to create a LoadBalancer Service to expose a simple web application.
Step 1: Deploy an Application
First, let's create a simple web application deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:latest
ports:
- containerPort: 80
Save this as web-app-deployment.yaml
and apply it:
kubectl apply -f web-app-deployment.yaml
Step 2: Create a LoadBalancer Service
Now, create a LoadBalancer Service to expose your application:
apiVersion: v1
kind: Service
metadata:
name: web-app-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: web-app
Save this as web-app-loadbalancer.yaml
and apply it:
kubectl apply -f web-app-loadbalancer.yaml
Step 3: Verify the Service
Check the Service status:
kubectl get services
Output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
web-app-lb LoadBalancer 10.96.150.12 34.123.456.78 80:30234/TCP 2m
The EXTERNAL-IP
field shows the IP address assigned by your cloud provider's load balancer. If it displays <pending>
, wait a few minutes for the load balancer to be provisioned.
Step 4: Access Your Application
Once the external IP is available, you can access your application using that IP:
curl http://34.123.456.78
Or simply open the IP in a web browser.
Advanced Configuration Options
Health Checks
Cloud providers use health checks to determine if your backend pods are healthy. You can configure these using annotations:
apiVersion: v1
kind: Service
metadata:
name: web-app-lb
annotations:
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: '10'
service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: '/healthz'
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: web-app
The annotations above are specific to AWS. Different cloud providers use different annotations.
Session Affinity
You can ensure that all requests from a single client are sent to the same pod using session affinity:
apiVersion: v1
kind: Service
metadata:
name: web-app-lb
spec:
type: LoadBalancer
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 80
selector:
app: web-app
Internal Load Balancer
In many cloud providers, you can create an internal load balancer (not exposed to the internet) using annotations:
apiVersion: v1
kind: Service
metadata:
name: internal-app
annotations:
service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: internal-app
LoadBalancer Implementations
Cloud Provider Load Balancers
Each cloud provider implements the LoadBalancer Service type differently:
- AWS: Provisions an Elastic Load Balancer (ELB) or Network Load Balancer (NLB)
- GCP: Creates a Cloud Load Balancer
- Azure: Sets up an Azure Load Balancer
- DigitalOcean: Provisions a DigitalOcean Load Balancer
On-Premise Solutions
For on-premise Kubernetes clusters, you can use:
- MetalLB: A load-balancer implementation for bare metal Kubernetes clusters
- OpenELB: An open-source load balancer implementation designed for bare metal environments
Let's look at a simple MetalLB configuration:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250
This configures MetalLB to assign IP addresses from the specified range to LoadBalancer Services.
Common Issues and Troubleshooting
Pending External IP
If your service's external IP remains in the <pending>
state:
- Verify your cloud provider credentials and configuration
- Check if you've reached your load balancer quota
- Look for error messages in the cloud controller manager logs:
kubectl logs -n kube-system -l k8s-app=cloud-controller-manager
High Latency
If you notice high latency or connection issues:
- Check the health check settings
- Ensure your pods are distributed across multiple availability zones
- Verify that your application is responding properly to health checks
Real-World Example: High-Availability Web Application
Let's deploy a complete high-availability web application with a database backend:
Frontend Deployment and Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: my-frontend-app:latest
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: frontend-lb
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: frontend
Backend Deployment and Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: my-backend-app:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP # Only frontend needs external exposure
ports:
- port: 8080
targetPort: 8080
selector:
app: backend
Summary
Kubernetes LoadBalancer Services provide a powerful way to expose your applications to the outside world when running in cloud environments. They:
- Leverage cloud provider load balancers for high availability and reliability
- Distribute traffic across multiple pods
- Provide a stable external IP address
- Simplify external access configuration
While LoadBalancer Services are primarily designed for cloud environments, solutions like MetalLB bring similar functionality to on-premise clusters.
When designing your Kubernetes network architecture, consider whether you need the full capabilities of a LoadBalancer Service or if other options like Ingress controllers might be more appropriate for your use case.
Additional Resources
- Kubernetes Services Documentation
- Cloud Provider LoadBalancer Configuration
- MetalLB for On-Premise Clusters
Exercises
- Deploy a simple web application and expose it using a LoadBalancer Service.
- Configure session affinity and observe the behavior when repeatedly accessing the service.
- If using a cloud provider, explore the various annotations available for customizing your load balancer.
- Create an internal load balancer and verify that it's not accessible from the internet.
- Set up MetalLB in a local Kubernetes cluster (like Minikube or Kind) and test LoadBalancer functionality.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)