# Deploy MetalLB as an on prem load-balancer for your  Kubernetes services

In traditional cloud provider environments, where network load balancers are available, you automatically get a single point of contact to any application running inside the cluster as shown in the picture below.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1611139859269/TvkQKw39X.png align="left")

On prem Kubernetes cluster doesn't have a proper cloud provider configured with a LoadBalancer support like you would have with AWS, GCP, Azure, etc. Therefore, when you create a service with type `LoadBalancer` it will sit in the pending state, waiting for an external IP as below.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1611139840672/KizdAbOH1.png align="left")

```plaintext
$ kubectl get svc
NAME         TYPE           CLUSTER-IP         EXTERNAL-IP  
fancyservice LoadBalancer   10.210.1.255       <pending>
```

To avoid the EXTERNAL-IP \*\*pending \*\* state of your Kubernetes services you can use MetalLB.

MetalLB aims to redress this imbalance by offering a Network LB implementation , so that Kubernetes services on custom clusters also “just work” as much as possible. In the example below, MetalLB take car to give an IP address to reach the application.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1611139799959/HOH6G6CAM.png align="left")

The deployment of MetalLB is quite simple. The current version is v0.9.5 and if you want to use an older version for any reason you can change the version in the URL of the yaml files.

```plaintext
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/metallb.yaml
```

> And on **first install only**

```plaintext
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
```

You should now have spun up a controller pod and one speaker per node.

```plaintext
$ kubectl -n metallb-system get pods
NAME                          READY   STATUS    RESTARTS   AGE
controller-5c9894b5cd-trlk5   1/1     Running   0          92d
speaker-2wwnk                 1/1     Running   0          92d
speaker-dt4j2                 1/1     Running   0          92d
speaker-mrhz9                 1/1     Running   0          92d
```

For the next steps you will need a range of free IP in the subnet of your Kubernetes Hosts. You can find the subnet and IP information of the nodes with `kubectl get nodes -o wide`

MetalLB will take control over the IP that you specify in the ConfigMap, in our example it will be a range from 10.210.36.220-10.210.36.229. This command will create the ConfigMap.

```plaintext
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 10.210.1.220-10.210.1.230
EOF
```

Let's test it with a simple NGINX helm deployment

```plaintext
kubectl create ns nginxdemo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install nginxdemo bitnami/nginx --set service.type=LoadBalancer --namespace nginxdemo
```

You will see that the service received an external IP from MetalLB

```plaintext
$ kubectl -n nginxdemo get service
NAME        TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
nginxdemo   LoadBalancer   10.252.57.89   10.210.36.223   80:31505/TCP   24s
```

And if your network allows it, you can now access the service using the external IP and the service port `http://10.210.36.223:80`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1611138416442/7vuHb1-wsF.png align="left")

Et voilà!!

If you want to clean the demo environment

```plaintext
helm uninstall nginxdemo && kubectl delete ns nginxdemo
```

Feel free to comment this article if you have questions.

cisel.ch

References:

https://metallb.universe.tf/
