Ludovic Alarcon

Ludovic Alarcon .

Kubernetes and Cloud technologies enthusiast, DevOps believer - Golang and Dotnet Developer

Add LoadBalancer Service with MetalLB on bare metal clusters

If you ever installed Kubernetes clusters on-premise, you probably noticed that you cannot use LoadBalancer service.
You could remplace it with NodePort service and manage your own LoadBalancer to distribute traffic. That’s is additional works and complexity you may not want handle.
Furthermore this leads to specificity between on-premise and cloud environment. Luckily, MetalLB comes to our rescue!


According to their documentation

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

MetalLB supports both BGP and Layer2 configuration. In this blog post, we will setup a Layer2 configuration with IPv4.


You need:


First of all, we need to add the helm repository and make sure all our repositories are up to date.

helm repo add metallb
helm repo update

We will then create the values.yaml to configure MetalLB to use Layer2 with our IPs adress range.
I used as subnet for my nodes and I will configure IPs from to for MetalLB.

# values.yaml
   - name: default
     protocol: layer2

Finally, we will create a dedicated namespace metallb-system and install the helm chart in it

> kubectl create ns metallb-system

> helm install metallb metallb/metallb -f values.yaml -n metallb-system

We can verify the configuration (output is cut for clarity)

> kubectl get cm metallb -n metallb-system -oyaml
apiVersion: v1
  config: |
    - addresses:
      name: default
      protocol: layer2
kind: ConfigMap

When we create a LoadBalancer service, the next available address will be pick by MetalLB in the address pool range we defined.

You can find advanced configuration and BGP on documentation

LoadBalancer Service in Action

Let’s deploy an nginx pod and expose it as a LoadBalancer service.

> kubectl run nginx --image=nginx
> kubectl expose pod nginx --type=LoadBalancer --port 80

Let’s verify we got an external IP and it’s one in our adress pool.

> kubectl get svc
NAME    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx   LoadBalancer    80:30850/TCP   5s

Great, last step, we will curl our endpoint and see if everything is working properly

> curl
<!DOCTYPE html>
<title>Welcome to nginx!</title>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href=""></a>.<br/>
Commercial support is available at
<a href=""></a>.</p>

<p><em>Thank you for using nginx.</em></p>

Success! With MetalLB we could add LoadBalancer service support on non-cloud Kubernetes clusters.