How to install and configure the MetalLB load balancer on the Kubernetes cluster? MetalLB uses a standard routing protocol to provide a network load-balancing solution for bare metal kubernetes clusters. Kubernetes doesn’t offer any network load balancers for bare-metal implementation. It does have peace to code to call the Cloud network load balancers if you are planning to host it in AWS, Azure, and GCP IaaS services. On bare-metal implementation, Nodeport is the only way to access the services outside the cluster. But Nodeport has its own limitations. You need to track the nodes which have the pods with exposed ports and port range allowed from 30,000 to 32,767 only.
MetalLB fills this gap by providing a load balancer to access the services outside the kubernetes cluster on the bare-metal implementation.
Pre-requisite:
- Kubernetes bare-metal cluster with version 1.13.0 or later.
- IPV4 subnet range for Metal Loadbalancer.
- Port 7946 must be allowed between nodes if you are using the firewall.
Installing & Configuring MetalLB:
1. Log into the kubernetes cluster with the required privileges.
2. Let’s identify the IP range for the MetalLB. Check the k8s node IP range.
lingesh@uamaster1:~$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME uamaster1 Ready control-plane,master 152d v1.23.5 192.168.23.132 <none> Ubuntu 20.04.4 LTS 5.4.0-125-generic containerd://1.6.2 uaworker1 Ready <none> 152d v1.23.5 192.168.23.133 <none> Ubuntu 20.04.4 LTS 5.4.0-125-generic containerd://1.6.2 uaworker2 Ready <none> 152d v1.23.5 192.168.23.134 <none> Ubuntu 20.04.4 LTS 5.4.0-125-generic containerd://1.6.2 lingesh@uamaster1:~$
In my case, the network is 192.168.23.1/24
3. Use “sipcalc” to know your IP range.
lingesh@uamaster1:~$ sipcalc 192.168.23.1/24 -[ipv4 : 192.168.23.1/24] - 0 [CIDR] Host address - 192.168.23.1 Host address (decimal) - 3232241409 Host address (hex) - C0A81701 Network address - 192.168.23.0 Network mask - 255.255.255.0 Network mask (bits) - 24 Network mask (hex) - FFFFFF00 Broadcast address - 192.168.23.255 Cisco wildcard - 0.0.0.255 Addresses in network - 256 Network range - 192.168.23.0 - 192.168.23.255 Usable range - 192.168.23.1 - 192.168.23.254 - lingesh@uamaster1:~$
4. For MetalLB, You need to enable strict ARP if the Kube-proxy is using IPVS mode.
lingesh@uamaster1:~$ kubectl describe configmaps -n kube-system kube-proxy |egrep "mode|strict" strictARP: true mode: ipvs lingesh@uamaster1:~$
5. Creates a namespace called “metallb-system” and install MetalLB using the manifest. Kindly refer MetalLB installation page to find the correct manifest URL.
lingesh@uamaster1:~$ kubectl create ns metallb-system lingesh@uamaster1:~$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml -n metallb-system
You can also install MetalLB using a helm chart.
lingesh@uamaster1:~$ helm repo add metallb https://metallb.github.io/metallb lingesh@uamaster1:~$ helm install metallb metallb/metallb
6. Verify the MetalLB installation.
lingesh@uamaster1:~$ kubectl get all -n metallb-system NAME READY STATUS RESTARTS AGE pod/controller-65b5d5b754-wslgv 1/1 Running 0 61s pod/speaker-cc7sp 1/1 Running 0 32m pod/speaker-cqqrc 1/1 Running 0 6m24s pod/speaker-rcdb2 1/1 Running 0 32m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/webhook-service ClusterIP 10.233.54.207 <none> 443/TCP 32m NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/speaker 3 3 3 3 3 kubernetes.io/os=linux 32m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/controller 1/1 1 1 32m NAME DESIRED CURRENT READY AGE replicaset.apps/controller-65b5d5b754 1 1 1 32m lingesh@uamaster1:~$
7. Configure the address pool for the MetalLB. Create a manifest like below.
apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 192.168.23.150-192.168.23.250
8. Create the config map using the kubectl create command.
lingesh@uamaster1:~$ kubectl create -f metallb.yaml -n metallb-system configmap/config created lingesh@uamaster1:~$
Test the MetalLB LoadBalancer using nginx deployment
1. I have an existing nginx deployment and have yet to expose it to the load balancer
lingesh@uamaster1:~$ kubectl get all -n nginx-test NAME READY STATUS RESTARTS AGE pod/nginx-deployment-74d589986c-lxkfq 1/1 Running 0 33m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-deployment 1/1 1 1 33m NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-deployment-74d589986c 1 1 1 33m
2. Expose the nginx deployment to LoadBalancer.
lingesh@uamaster1:~$ kubectl expose deployment.apps/nginx-deployment --port 80 --type LoadBalancer -n nginx-test service/nginx-deployment exposed lingesh@uamaster1:~$ kubectl get all -n nginx-test NAME READY STATUS RESTARTS AGE pod/nginx-deployment-74d589986c-lxkfq 1/1 Running 0 59m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/nginx-deployment LoadBalancer 10.233.11.165 192.168.23.153 80:30218/TCP 2s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-deployment 1/1 1 1 59m NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-deployment-74d589986c 1 1 1 59m lingesh@uamaster1:~$
3. Try to access the service using the external IP which was allocated by the MetalLB.
Conclusion:
We have successfully deployed the MetalLB load balancer on the bare metal Kubernetes cluster. Tested the Loadbalancer functionality by exposing the existing nginx deployment. As part of the Baremetal K8s series, we have completed step 2 successfully.
- kubernetes cluster setup – k8s LAB using Kubespary – Part 1
- Kubernetes bare metal load balancer – MetalLB deployment – Part 2 (You are here now)
Adama says
Hello,
I followed the procedure on a 3-node cluster mounted on OVH vps, but I have a pending status in EXTERNAL-IP:
> k get no -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master Ready control-plane,master 6d21h v1.25.5 51.178.24.169 Debian GNU/Linux 11 (bullseye) 5.10.0-21-cloud-amd64 containerd://1.6.20
k8s-worker1 Ready worker 6d21h v1.25.5 51.178.26.103 Debian GNU/Linux 11 (bullseye) 5.10.0-21-cloud-amd64 containerd://1.6.20
k8s-worker2 Ready worker 6d21h v1.25.5 51.178.28.148 Debian GNU/Linux 11 (bullseye) 5.10.0-21-cloud-amd64 containerd://1.6.20
——————————————
kubectl get all -n nginx-test
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-588c7b4b9f-xnmpf 1/1 Running 0 3m38s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-deployment LoadBalancer 10.104.193.184 80:30518/TCP 3m30s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 1/1 1 1 3m38s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-588c7b4b9f 1 1 1 3m38s