MetalLB Load Balancer for Bare Metal Kubernetes

Prashant Lakhera
3 min readFeb 4, 2021

To read the complete blog

What is MetalLB?

As per official documentation

MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols.

Now the question is why do we need it?

In cases where you are deploying your Kubernetes Cluster outside Cloud solutions(AWS, GCP) you need a way to expose your service outside the cluster. In those cases you can expose your service using NodePort using port range 30000–32767 but everytime your customer need to access your service he need to specify this higher order port. If you trying to use LoadBalancer service in bare metal all, you will see your service will be in pending state forever.

How it works?

If we take an example of cloud environment, the creation and allocation of external IP is the responsibility of the cloud provider. In case of bare metal environment its the responsibility of MetalLB. MetalLB assigned the IP from the reserved pool of IP addresses which we allocate them via configmap(you will see this in the later configmap section). Once the external IP is assigned it need to redirect traffic from external IP to the cluster and for that it uses protocol like ARP or BGP.

Let see this with the help of an example

  • Create a deployment
kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
  • Expose the deployment
kubectl expose deploy nginx --port 80 --type LoadBalancer
service/nginx exposed
  • If you check the deployment the external-ip is in pending state
kubectl get svc nginx          
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.96.255.195 <
pending> 80:30681/TCP 46s

To fix this issue, we can implement a solution like MetalLB.

Installation

  • First step is to apply the manifests, which will create the namespace metallb-system
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/namespace.yaml
namespace/metallb-system created

To verify it

kubectl get ns                                                                                    
NAME STATUS AGE
default Active 20h
kube-node-lease Active 20h
kube-public Active 20h
kube-system Active 20h
local-path-storage Active 20h
metallb-system Active 4s
  • In the next step we will apply one more manifests which will create deployment, daemonset, role and cluster role binding, service account and pod security for metallb in metallb-system namespace.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/metallb.yaml
podsecuritypolicy.policy/controller created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
role.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
rolebinding.rbac.authorization.k8s.io/pod-lister created
daemonset.apps/speaker created
deployment.apps/controller created

To verify it

kubectl get all -n metallb-system                                                               
NAME READY STATUS RESTARTS AGE
pod/controller-65db86ddc6-f7brp 1/1 Running 0 2m13s
pod/speaker-htxfd 0/1
CreateContainerConfigError 0 2m13s
pod/speaker-kcct8 0/1
CreateContainerConfigError 0 2m13s
pod/speaker-m2svj 0/1
CreateContainerConfigError 0 2m13s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/speaker 3 3 0 3 0 kubernetes.io/os=linux 2m13s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/controller 1/1 1 1 2m13s
NAME DESIRED CURRENT READY AGE
replicaset.apps/controller-65db86ddc6 1 1 1 2m13s
  • If you look at the pod, you have two types of pod after applying the manifests, controller and speaker.controller is the cluster-wide MetalLB controller, and responsible of IP assignment.speaker on the other hand is a deamonser that is it going to be installed on each node in your cluster and advertises services with assigned IPs using various advertising strategies.
  • First time when you install the metallb you will see this error, in order to fix it you need to create the secret. The memberlist secret contains the secretkey to encrypt the communication between speakers for the fast dead node detection.
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
secret/memberlist created
  • If you verify the pod again, it should be in running state now
kubectl get all -n metallb-system                                                                                
NAME READY STATUS RESTARTS AGE
pod/controller-65db86ddc6-f7brp 1/1 Running 0 6m28s
pod/speaker-htxfd 1/1 Running 0 6m28s
pod/speaker-kcct8 1/1 Running 0 6m28s
pod/speaker-m2svj 1/1 Running 0 6m28s

--

--

Prashant Lakhera

AWS Community Builder, Ex-Redhat, Author, Blogger, YouTuber, RHCA, RHCDS, RHCE, Docker Certified,4XAWS, CCNA, MCP, Certified Jenkins, Terraform Certified, 1XGCP