MetalLB On-prem Kubernetes Cluster LoadBalancer
Kubernetes ships with a Network LB implementation that’s primarily suited for IaaS platforms such as AWS, GCP, Azure. For On-prem Kubernetes cluster deployment, Kubernetes does not offer any Network LoadBalancer implementation.

We are left mostly with using NodePort or Cluster IP if we want to have external traffic for our applications. I recently stumbled into MetalLB that provides Network Load-Balancing for Kubernetes deployed on Bare-metal servers.
I’ll be sharing in this post how I installed MetalLB on my Kubernetes Cluster.
Install MetalLB by applying the manifest available at https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml
This will create resources which basically is related to access control. It will also create metallb-system/controller that handles IP Address assignment.
It also creates a metallb-system/speaker which handles the protocol(s) to make the service reachable.
[k8smaster ~]# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml
namespace/metallb-system 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
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
daemonset.apps/speaker created
deployment.apps/controller created
[k8smaster ~]#
Once created we could check the pods under metallb-systems namespace
[k8smaster ~]# kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-7cc9c87cfb-qj5gb 1/1 Running 0 28s
speaker-8bn5d 1/1 Running 0 29s
[k8smaster ~]#
I will create a Layer2 configuration as its the most simplest way to test this.
Basically I provided a set of available IP range (which my DHCP server provides ) to MetalLB.
[k8smaster ~]# cat mlb-layer2-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: my-ip-space
protocol: layer2
addresses:
- 192.168.0.240-192.168.0.250
[k8smaster ~]#[k8smaster ~]# kubectl apply -f mlb-layer2-config.yml
configmap/config created
[k8smaster ~]#[k8smaster ~]# kubectl describe ConfigMap config --namespace metallb-system
Name: config
Namespace: metallb-system
Labels: <none>
Annotations: <none>Data
====
config:
----
address-pools:
- name: my-ip-space
protocol: layer2
addresses:
- 192.168.0.240-192.168.0.250Events: <none>
[k8smaster ~]#
Let’s now test this LoadBalancer by creating the following deployment and service resources.
[development python-webapp]# cat deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: awesome-webapp
labels:
app: awesome-webapp
spec:
replicas: 2
selector:
matchLabels:
app: awesome-webapp
template:
metadata:
labels:
app: awesome-webapp
spec:
containers:
- name: python-webapp
image: gcr.io/kube-cluster-234414/python-webapp:2
ports:
- containerPort: 8080[development python-webapp]#[development python-webapp]# cat mlb-service.yml
apiVersion: v1
kind: Service
metadata:
name: awesome-webapp-mlb-service
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
selector:
app: awesome-webapp
type: LoadBalancer[development python-webapp]#[development python-webapp]# kubectl apply -f deploy.yml
deployment.apps/awesome-webapp created
[development python-webapp]# kubectl apply -f mlb-service.yml
service/awesome-webapp-mlb-service created
[development python-webapp]#
I deployed a replica set with 2 instance that is accessible via a LoadBalancer service.
[development python-webapp]# kubectl get service,deploy,po
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/awesome-webapp-mlb-service LoadBalancer 10.103.126.242 192.168.0.240 80:31485/TCP 16mNAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/awesome-webapp 2/2 2 2 16mNAME READY STATUS RESTARTS AGE
pod/awesome-webapp-6d9b76bd54-6hqzc 1/1 Running 0 12m
pod/awesome-webapp-6d9b76bd54-md6xf 1/1 Running 0 12m
[development python-webapp]#
Now I can access this application using the External IP provided.


Although still in it’s early phase and with critical limitations, MetalLB looks to be promising for Kubernetes Cluster deployments on bare-metal servers. You can find more information about MetalLB at https://metallb.universe.tf.