Demystifying MetalLB: A Comprehensive Guide to Load Balancing for BareMetal Kubernetes in L2Mode
arobytes
Posted on February 11, 2024
Why?
Kubernetes does not offer an implementation of network load balancers (Services of type Load Balancer) for bare-metal clusters.
Bare-metal cluster operators are left with two lesser tools to bring user traffic into their clusters, “Node Port” and “externalIPs” services. Both of these options have significant downsides for production use, which makes bare-metal clusters second-class citizens in the Kubernetes ecosystem.
MetalLB aims to redress this imbalance by offering a network load balancer implementation that integrates with standard network equipment, so that external services on bare-metal clusters also “just work” as much as possible.
Understanding MetalLB
MetalLB hooks into your Kubernetes cluster, and provides a network load-balancer implementation. In short, it allows you to create Kubernetes services of type LoadBalancer in clusters that don’t run on a cloud provider, and thus cannot simply hook into paid products to provide load balancers.
It has two features that work together to provide this service: address allocation, and external announcement.
Address Allocation
LoadBalancer in Cloud-Provider: In a Kubernetes cluster on a cloud provider, you request a load balancer, and your cloud platform assigns an IP address to you.
LoadBalancer in BareMetal: In a bare-metal cluster, MetalLB is responsible for that allocation.
How It Workes: MetalLB cannot create IP addresses out of thin air, so we do have to give it pools of IP addresses that it can use. MetalLB will take care of assigning and unassigning individual addresses as services come and go, but it will only ever hand out IPs that are part of its configured pools.
Current Kubernetes Architecture
Installation
Installation With Helm
root@devmaster:~# helm repo add metallb https://metallb.github.io/metallb
root@devmaster:~# helm install metallb metallb/metallb
root@devmaster:~# helm repo list | grep -i metallb
metallb https://metallb.github.io/metallb
Verify Installation
root@devmaster:~# kubectl get all -n metallb-system
NAME READY STATUS RESTARTS AGE
pod/controller-586bfc6b59-pcq87 1/1 Running 0 1d
pod/speaker-2zwg4 1/1 Running 0 1d
pod/speaker-8n84l 1/1 Running 0 1d
pod/speaker-zdxv6 1/1 Running 0 1d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/webhook-service ClusterIP 10.111.217.93 <none> 443/TCP 1d
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 1 1 1 1 1 kubernetes.io/os=linux 1d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 0/1 1 0 1d
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-586bfc6b59 1 1 0 1d
Component in Metalb-system
Controller: The MetalLB controller watches Kubernetes service objects and configures the speaker(s) to announce the services' IP addresses. It ensures that the load balancing configuration matches the desired state specified in Kubernetes service objects.
Speaker: As mentioned earlier, the speaker(s) in MetalLB are responsible for advertising the IP addresses of services within the cluster to the local network. They handle the actual routing of traffic to the appropriate endpoints based on the service definitions.
AddressPool: Address pool configuration is a crucial aspect that defines the range of IP addresses that MetalLB can allocate to services within a Kubernetes cluster.
Service Account and RBAC (Role-Based Access Control) Resources: MetalLB components usually require appropriate RBAC permissions to function correctly within the Kubernetes cluster. The metalb-system namespace may contain ServiceAccount, ClusterRole, and RoleBinding resources to grant the necessary permissions.
Create IP Address Pool
root@devmaster:~# cat metallb-system.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: cheap
namespace: metallb-system
spec:
addresses:
- 172.16.16.150-172.16.16.20
root@devmaster:~# kubectl apply -f metallb-system.yaml
root@devmaster:~# kubectl get ipaddresspool -n metallb-system
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
cheap true false ["172.16.16.150-172.16.16.200"]
Let's deploy sample application and verify Loadbalancer IP is getting assigned to Application.
root@devmaster:~# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Deploy the application in demo ns
root@devmaster:~# kubectl create ns demo
namespace/demo created
root@devmaster:~# kubectl apply -f nginx.yaml -n demo
Verify the svc in demo ns
root@devmaster:~# kubectl get svc -n demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.97.54.239 <none> 80/TCP 3m25s
Edit the svc and change the type from ClusterIP to LoadBalancer and same the file
root@devmaster:~# kubectl edit svc nginx-service -n demo
Verify the Ip get Assigned as Load balancer
root@devmaster:~# kubectl get svc -n demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service LoadBalancer 10.102.244.73 172.16.16.157 80:31908/TCP 6m7s
Login to Browser and access the application with ip 172.16.16.157
Posted on February 11, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.