Six tools to Simplify Kubernetes Journey — Day 2 — MetalLB Load Balancer for Bare Metal Kubernetes
For complete blog list please check https://www.101daysofdevops.com/courses/101-days-of-kubernetes/ (You need to register)
What is MetalLB?
As per official documentation
MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols.
Now the question is, why do we need it?
In cases where you are deploying your Kubernetes Cluster outside Cloud solutions(AWS, GCP), you need a way to expose your service outside the cluster. You can use NodePort to expose your service using port range 30000–32767, but every time your customer needs to access your service, they need to specify this higher-order port. If you are trying to use the LoadBalancer service in bare metal, you will see your service will be pending forever. In these scenarios, you can use MetlabLB.
How does it work?
If we take an example of a cloud environment, the creation and allocation of external IP is the cloud provider’s responsibility. In the case of a bare-metal environment, it’s the responsibility of MetalLB. MetalLB assigned the IP from the reserved pool of IP addresses, which we allocate via configmap(you will see this in the later configmap section). Once the external IP is assigned, it needs to redirect traffic from the external IP to the cluster, and for that, it uses a protocol like ARP or BGP.
Let see this with the help of an example
- Create a deployment
kubectl create deployment nginx --image=nginx
- Expose the deployment
kubectl expose deploy nginx --port 80 --type LoadBalancer
- If you check the deployment the external-ip is in the pending state
kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.96.255.195 <pending> 80:30681/TCP 46s
To fix this issue, we can implement a solution like MetalLB.
- First step is to apply the manifests, which will create the namespace metallb-system
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/namespace.yamlnamespace/metallb-system created
- To verify it
kubectl get nsNAME STATUS AGEdefault Active 24hkube-node-lease Active 24hkube-public Active 24hkube-system Active 24hlocal-path-storage Active 24hmetallb-system Active 44s
- We will apply one more manifest in the next step, which will create the deployment, daemonset, role and cluster role binding, service account, and pod security for metallb in metallb-system namespace.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.3/manifests/metallb.yam
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+podsecuritypolicy.policy/controller createdpodsecuritypolicy.policy/speaker createdserviceaccount/controller createdserviceaccount/speaker createdclusterrole.rbac.authorization.k8s.io/metallb-system:controller createdclusterrole.rbac.authorization.k8s.io/metallb-system:speaker createdrole.rbac.authorization.k8s.io/config-watcher createdrole.rbac.authorization.k8s.io/pod-lister createdrole.rbac.authorization.k8s.io/controller createdclusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller createdclusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker createdrolebinding.rbac.authorization.k8s.io/config-watcher createdrolebinding.rbac.authorization.k8s.io/pod-lister createdrolebinding.rbac.authorization.k8s.io/controller createddaemonset.apps/speaker createddeployment.apps/controller createdl
- To verify it
kubectl get all -n metallb-systeNAME READY STATUS RESTARTS AGEpod/controller-77c44876d-b8gsw 1/1 Running 0 42spod/speaker-wqxlq 1/1 Running 0 42s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGEdaemonset.apps/speaker 1 1 1 1 1 kubernetes.io/os=linux 42s
NAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/controller 1/1 1 1 42s
NAME DESIRED CURRENT READY AGEreplicaset.apps/controller-77c44876d 1 1 1 42sm
- If you look at the pod, you have two types of pod created after applying the manifests, controller and speaker. The controller is the cluster-wide MetalLB controller and is responsible for IP assignment. The speaker is a deamonset that will be installed on each node in your cluster and advertises services with assigned IPs using various advertising strategies.
- As the last step, you need to define the configmap. Depending on your environment, you can set the operation mode to either Layer 2 or BGP and the external IP range. For this demo, I will use the protocol as layer2 and addresses as 172.18.0.200–172.18.0.250 as my Kubernetes node is running in the subnet range(check the output of kubectl get nodes -o wide command).
kubectl get nodes -o widNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEkind-control-plane Ready control-plane,master 24h v1.21.1 172.18.0.2 <none> Ubuntu 21.04 5.10.47-linuxkit containerd://1.5.2e
- Configmap will look like this
- name: my-ip-space
- This time if you check the service, you will see that metallb assigned the external ip to it from the pool you defined under configmap.
kubectl get svc nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEnginx LoadBalancer 10.96.131.55 172.18.0.200 80:30355/TCP 10m
Metallb allows you to create Loadbalancer for your service without deploying your cluster in the cloud environment. So far, I have explored the layer2 mode, which doesn’t need any external hardware. Another mode is BGP, which is production-ready but requires changes on the network end. Please let me know if you have explored BGP mode or any other functionality provided by metallb, which I am missing in this blog.