Demystifying MetalLB: A Comprehensive Guide to Load Balancing for BareMetal Kubernetes in L2Mode
Published: 2024-02-11 11:53:05


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zrt59da6eczlr8qgcnn.png)

**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._


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6ga6pgc14gp0in0ugje.png)


**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**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsre4k3m502tohdr91cg.png)





**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

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fm4cykq74zsk8h8q0gbf.png)

_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_ 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1nzswng0l7qfl24ce0vl.png)