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:
- A working Kubernetes cluster in version 1.13 or above. If you don’t have one, you can setup a local cluster with Kubeadm
- A range of IPs on the same subnet than your nodes.
- A Network Addon that can coexist with MetalLB
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.