“MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols.”
Reference: https://metallb.universe.tf/
Kubernetes does not offer an implementation of network load-balancers (Services of type LoadBalancer) for bare metal clusters. The implementations of Network LB that Kubernetes does ship with are all glue code that calls out to various IaaS platforms (GCP, AWS, Azure…). If you’re not running on a supported IaaS platform (GCP, AWS, Azure…), Load Balancers will remain in the “pending” state indefinitely when created.
You need to add a route to your local machine to access the internal network of Virtualbox.
~$ sudo ip route add 192.168.4.0/27 via 192.168.4.30 dev vboxnet0
~$ sudo ip route add 192.168.4.32/27 via 192.168.4.62 dev vboxnet0
~$ sudo ip route add 192.168.2.0/24 via 192.168.4.254 dev vboxnet0
We need to get the BusyBox IP to access it via ssh
~$ vboxmanage guestproperty get busybox "/VirtualBox/GuestInfo/Net/0/V4/IP"
Expected output:
Value: 192.168.4.57
Use the returned value to access.
~$ ssh [email protected]
LoadBalancer manifest:
apiVersion: v1
kind: Service
metadata:
name: load-balancer-service
spec:
selector:
app: guestbook
tier: frontend
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
-
Apply the LoadBalancer service deploy from the
kube-service-load-balancer
file:debian@busybox:~$ kubectl apply -f https://raw.githubusercontent.com/mvallim/kubernetes-under-the-hood/master/services/kube-service-load-balancer.yaml
The response should look similar to this:
service/load-balancer-service created
-
Query the state of service
load-balancer-service
debian@busybox:~$ kubectl get service load-balancer-service -o wide
The response should look similar to this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR load-balancer-service LoadBalancer 10.107.119.217 <pending> 80:30154/TCP 9s app=guestbook,tier=frontend
If you look at the status on the
EXTERNAL-IP
it is<pending>
because we need configure MetalLB to provide IP toLoadBalancer
service.
To install MetalLB, apply the manifest:
-
Apply the MetalLB manifest
namespace
from thenamespace.yaml
file:debian@busybox:~$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/namespace.yaml
The response should look similar to this:
namespace/metallb-system created
-
Apply the MetalLB manifest
controller
andspeaker
from themetallb.yaml
file:debian@busybox:~$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/metallb.yaml
The response should look similar to this:
podsecuritypolicy.policy/controller created podsecuritypolicy.policy/speaker 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 role.rbac.authorization.k8s.io/pod-lister 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 rolebinding.rbac.authorization.k8s.io/pod-lister created daemonset.apps/speaker created deployment.apps/controller created
-
Create the MetalLB scret
memberlist
:debian@busybox:~$ kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
The response should look similar to this:
secret/memberlist created
-
Query the state of deploy
debian@busybox:~$ kubectl get deploy -n metallb-system -o wide
The response should look similar to this:
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR controller 1/1 1 1 28s controller metallb/controller:v0.9.3 app=metallb,component=controller
This will deploy MetalLB to your cluster, under the metallb-system
namespace. The components in the manifest are:
- The
metallb-system/controller
deployment. This is the cluster-wide controller that handles IP address assignments. - The
metallb-system/speaker
daemonset. This is the component that speaks the protocol(s) of your choice to make the services reachable. - Service accounts for the controller and speaker, along with the RBAC permissions that the components need to function.
The installation manifest does not include a configuration file. MetalLB’s components will still start, but will remain idle until you define and deploy a configmap
. The memberlist
secret contains the secretkey
to encrypt the communication between speakers for the fast dead node detection.
Reference : https://metallb.universe.tf/installation/#installation-by-manifest
Based on the planed network configuration (here) we will have a metallb-config.yaml
as below:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.2.2-192.168.2.125
-
Apply the MetalLB configmap from the
metallb-config.yaml
file:debian@busybox:~$ kubectl apply -f https://raw.githubusercontent.com/mvallim/kubernetes-under-the-hood/master/metallb/metallb-config.yaml
-
Query the state of deploy
debian@busybox:~$ kubectl get deploy controller -n metallb-system -o wide
The response should look similar to this:
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR controller 1/1 1 1 5m34s controller metallb/controller:v0.8.3 app=metallb,component=controller
-
Query the state of service
load-balancer-service
debian@busybox:~$ kubectl get service load-balancer-service -o wide
The response should look similar to this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR load-balancer-service LoadBalancer 10.107.119.217 192.168.2.10 80:30154/TCP 3m4s app=guestbook,tier=frontend
Now if you look at the status on the
EXTERNAL-IP
it is192.168.2.10
and can be access directly from external, without usingNodePort
orClusterIp
. Remember this IP192.168.2.10
isn't assigned to any node. In this example of service we can access usinghttp://192.168.2.10
.
Deleting the services
-
Run the following commands to delete service.
debian@busybox:~$ kubectl delete service load-balancer-service
The responses should be:
service "load-balancer-service" deleted
-
Query the list of service:
debian@busybox:~$ kubectl get services
The response should be this:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d2h