Ludovic Alarcon

Ludovic Alarcon .

Kubernetes and Cloud enthusiast - 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!

MetalLB

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.

Prerequisites

You need:

Installation

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

helm repo add metallb https://metallb.github.io/metallb
helm repo update

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

# values.yaml
configInline:
  address-pools:
   - name: default
     protocol: layer2
     addresses:
     - 10.0.0.240-10.0.0.250

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
data:
  config: |
    address-pools:
    - addresses:
      - 10.0.0.240-10.0.0.250
      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   10.104.223.189   10.0.0.240    80:30850/TCP   5s

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

> curl 10.0.0.240
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<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="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

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

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