Demystifying MetalLB: A Comprehensive Guide to Load Balancing for BareMetal Kubernetes in L2Mode

arobytes

arobytes

Posted on February 11, 2024

Demystifying MetalLB: A Comprehensive Guide to Load Balancing for BareMetal Kubernetes in L2Mode

Image description

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

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

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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"]

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

Deploy the application in demo ns

root@devmaster:~# kubectl create ns demo
namespace/demo created
root@devmaster:~# kubectl apply -f nginx.yaml -n demo

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

Edit the svc and change the type from ClusterIP to LoadBalancer and same the file

root@devmaster:~#  kubectl edit svc nginx-service -n demo

Enter fullscreen mode Exit fullscreen mode

Image description

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

Enter fullscreen mode Exit fullscreen mode

Login to Browser and access the application with ip 172.16.16.157

Image description

💖 💪 🙅 🚩
arobytes
arobytes

Posted on February 11, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related