Deploy MetalLB Load Balancer on Kubernetes.

What is this load balancer, and what is it good for?

A load balancer on Kubernetes is a mechanism to distribute network traffic across multiple pods to ensure no single pod becomes a bottleneck, thus improving the availability and reliability of your applications. Kubernetes supports several types of load balancers, each designed to address different needs and environments.

MetalLB is an open-source load balancer for Kubernetes clusters. Unlike cloud-based load balancers, which are often provided by cloud service providers, This one is designed to work in on-premises or bare-metal Kubernetes clusters. It provides a way for services to be exposed to the external network, enabling them to receive traffic from outside the cluster.

Key Features:

Layer 2 (ARP/NDP) and Layer 3 (BGP) Modes:

Layer 2 Mode: Uses ARP (Address Resolution Protocol) or NDP (Neighbor Discovery Protocol) to make Kubernetes services reachable on the local network.
Layer 3 Mode: Uses BGP (Border Gateway Protocol) to advertise the service IPs to the local network’s routers.

Service Types:

Supports Kubernetes LoadBalancer type services, which traditionally are used with cloud providers’ load balancers.
Allows on-premises Kubernetes clusters to use LoadBalancer services without requiring a cloud provider.
IP Address Management:

Metal can handle pools of IP addresses, ensuring that services get allocated IPs from a predefined pool.
Configurable to use specific IP address ranges to avoid conflicts with existing network infrastructure.
Easy to Deploy and Configure:

Simple YAML manifests for deployment in a Kubernetes cluster.

I’ve finished installing a VPN on my lab RKE cluster (here is a link to WireGuard deployment tutorial) and was thinking about what comes next… I thought about maybe adding a couple of worker nodes to my lonely RKE, but that would probably be done after i deploy a Load balancer…. Or maybe I should deploy the Load balancer after I add more nodes?? Yaahh… anyway, I’m deploying the Load Balancer now.

A quick Google search revealed to me that the best load balancer for home labs is MetalLB. I took a peek at its official page, and the installation seemed quite straightforward. Without dwelling too long, I started with deploying the mainfest…

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml

After about 30 seconds or so, all the resources were ready, and I moved on to the configuration phase. At this stage, I needed to create two more YAML files. One containing the IP address ranges that the load balancer would be allowed to assign, and the other enabling the exposure of endpoints to objects in the network, that done with ARP requests”

Create ‘ipaddresspool.yaml’ file and paste in to it the following content.
change the ‘addresses’ field according to your needs.
This network chunk is not being assigned by the DHCP so no need to worry about collisions.

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.66.100-192.168.66.150

Next create the ‘l2advertisement.yaml’, with the following content.
This resource is responsible for the advertisement of the IP addresses assigned by the Load balancer.

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

Run both files

k apply -f ipaddresspool.yaml \
k apply -f l2advertisement.yaml

So the next step is just to test it and validate the promise….
let’s go with the simplest method, let’s deploy an NGINX, It’ll take a second.

Create a ‘nginx-deployment.yaml’ and paste in te following content.
it’ll create a namespace, service and deployment for NGINX.
notice that the service is type ‘LoadBalancer’, we are gonna try get an external address from the LB.

apiVersion: v1
kind: Namespace
metadata:
  name: temp-ns
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  namespace: temp-ns
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  namespace: temp-ns
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Run the deployment.

k apply -f nginx-deployment.yaml

And now you can see the external IP is assigned.

Now just to be sure let’s make a curl from a machine on the same network.