MetalLB for K8S Cluster on Bare-Metal

On Bare-metal servers, K8S doesn’t offer any LoadBalancer implementation.  K8S ships with a Network LB implementation that’s primarily suited/works with IaaS platforms.

We are left mostly with using NodePort if we want to get external traffic to our cluster.

I recently stumbled into MetalLB that provides Network Load-Balancing for K8S deployed on Bare-metal servers. I’ll be sharing in this post how I installed MetalLB on my K8S Cluster.

Install MetalLB by applying the manifest available at https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

This will create resources which basically is related to access control. It will also create metallb-system/controller that handles IP Address assignment.
It also creates a metallb-system/speaker which handles the protocol(s) to make the service reachable.

[k8smaster ~]# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml
namespace/metallb-system created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
daemonset.apps/speaker created
deployment.apps/controller created
[k8smaster ~]#

Once created we could check the pods under metallb-systems namespace

[k8smaster ~]# kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-7cc9c87cfb-qj5gb 1/1 Running 0 28s
speaker-8bn5d 1/1 Running 0 29s
[k8smaster ~]#

I will create a Layer2 configuration as its the most simplest way to test this.

Basically I provided a set of available IP range (which my DHCP server provides ) to MetalLB.

[k8smaster ~]# cat mlb-layer2-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
 namespace: metallb-system
 name: config
data:
 config: |
 address-pools:
 - name: my-ip-space
 protocol: layer2
 addresses:
 - 192.168.0.240-192.168.0.250
[k8smaster ~]#



[k8smaster ~]# kubectl apply -f mlb-layer2-config.yml
configmap/config created
[k8smaster ~]#



[k8smaster ~]# kubectl describe ConfigMap config --namespace metallb-system
Name: config
Namespace: metallb-system
Labels: <none>
Annotations: <none>

Data
====
config:
----
address-pools:
- name: my-ip-space
 protocol: layer2
 addresses:
 - 192.168.0.240-192.168.0.250

Events: <none>
[k8smaster ~]#

Let’s now test this LoadBalancer by creating the following deployment and service resources.

[development python-webapp]# cat deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: awesome-webapp
 labels:
 app: awesome-webapp
spec:
 replicas: 2
 selector:
 matchLabels:
 app: awesome-webapp
 template:
 metadata:
 labels:
 app: awesome-webapp
 spec:
 containers:
 - name: python-webapp
 image: gcr.io/kube-cluster-234414/python-webapp:2
 ports:
 - containerPort: 8080

[development python-webapp]#

[development python-webapp]# cat mlb-service.yml
apiVersion: v1
kind: Service
metadata:
 name: awesome-webapp-mlb-service
spec:
 ports:
 - name: http
 port: 80
 protocol: TCP
 targetPort: 8080
 selector:
 app: awesome-webapp
 type: LoadBalancer

[development python-webapp]#



[development python-webapp]# kubectl apply -f deploy.yml
deployment.apps/awesome-webapp created
[development python-webapp]# kubectl apply -f mlb-service.yml
service/awesome-webapp-mlb-service created
[development python-webapp]#

I deployed a replica set with 2 instance that is accessible via a LoadBalancer service.

[development python-webapp]# kubectl get service,deploy,po
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/awesome-webapp-mlb-service LoadBalancer 10.103.126.242 192.168.0.240 80:31485/TCP 16m

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/awesome-webapp 2/2 2 2 16m

NAME READY STATUS RESTARTS AGE
pod/awesome-webapp-6d9b76bd54-6hqzc 1/1 Running 0 12m
pod/awesome-webapp-6d9b76bd54-md6xf 1/1 Running 0 12m
[development python-webapp]#

Now I can access this application using the External IP provided.

Although still in it’s early phase and with critical limitations, MetalLB looks to be promising for K8S deployments on bare-metal servers. You can find more information about MetalLB at https://metallb.universe.tf.