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

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

$ 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

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.

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

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.

$ 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.

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

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

$ 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

Et voilà!!

If you want to clean the demo environment

helm uninstall nginxdemo && kubectl delete ns nginxdemo

Feel free to comment this article if you have questions.

cisel.ch

References:

metallb.universe.tf

No Comments Yet