In this article we will look how we can get service type LoadBalancer in our cluster using MetalLB
Introduction
MetalLB provides a network load balancer implementation in our cluster
Allows you to create Kubernetes services of type LoadBalancer in clusters that don’t run on a cloud provider
Sets up MetalLB using layer2 protocol
We can send traffic directly to the load balancer’s external IP if the IP space is within the Docker IP space
Usage
- Create a simple cluster using the below configuration file
$ cat kind.yml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 name: dev nodes: - role: control-plane - role: worker - role: worker
$ kind create cluster --config kind.yml Creating cluster "dev" ... ✓ Ensuring node image (kindest/node:v1.26.3) 🖼 ✓ Preparing nodes 📦 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜 Set kubectl context to "kind-dev" You can now use your cluster with: kubectl cluster-info --context kind-dev
$ kubectl get nodes NAME STATUS ROLES AGE VERSION dev-control-plane Ready control-plane 68s v1.26.3 dev-worker Ready <none> 37s v1.26.3 dev-worker2 Ready <none> 37s v1.26.3
- Deploy MetalLB using the default manifests and verify the components are up and running
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml namespace/metallb-system created customresourcedefinition.apiextensions.k8s.io/addresspools.metallb.io created customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created serviceaccount/controller created serviceaccount/speaker created role.rbac.authorization.k8s.io/controller created role.rbac.authorization.k8s.io/pod-lister created clusterrole.rbac.authorization.k8s.io/metallb-system:controller created clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created rolebinding.rbac.authorization.k8s.io/controller created rolebinding.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 secret/webhook-server-cert created service/webhook-service created deployment.apps/controller created daemonset.apps/speaker created validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created
$ kubectl -n metallb-system get pods NAME READY STATUS RESTARTS AGE controller-577b5bdfcc-p7sb5 1/1 Running 0 76s speaker-cgmm4 1/1 Running 0 76s speaker-gwfqr 1/1 Running 0 76s speaker-jk684 1/1 Running 0 76s
- As we said earlier in the introduction part, we are using the layer2 protocol of MetalLB. For completing the layer2 configuration, we need to provide MetalLB a range of IP addresses it controls. This IP address range needs to be in the Docker kind network.
$ docker network inspect -f '{{.IPAM.Config}}' kind [{172.18.0.0/16 172.18.0.1 map[]} {fc00:f853:ccd:e793::/64 fc00:f853:ccd:e793::1 map[]}]
Now we want our load balancer IP range to come from this subclass and we can configure MetalLB to use 172.19.255.200 to 172.19.255.250 by creating IPAddressPool and L2Advertisement resources.
Create the necessary MetalLB resources using the below manifest file.
$ cat metallb.yml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: kind namespace: metallb-system spec: addresses: - 172.18.255.200-172.18.255.250 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind namespace: metallb-system spec: ipAddressPools: - kind
$ kubectl apply -f metallb.yml ipaddresspool.metallb.io/kind unchanged l2advertisement.metallb.io/kind created
$ kubectl -n metallb-system get ipaddresspools NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES kind true false ["172.18.255.200-172.18.255.250"] $ kubectl -n metallb-system get l2advertisements NAME IPADDRESSPOOLS IPADDRESSPOOL SELECTORS INTERFACES kind ["kind"]
Deploy our Application
- Create an Nginx pod using the below manifest file and verify its status
$ cat nginx.yml apiVersion: v1 kind: Pod metadata: labels: run: nginx name: nginx spec: containers: - image: nginx name: nginx ports: - containerPort: 80
$ kubectl apply -f nginx.yml pod/nginx created
$ kubectl get pods nginx NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 23s
- Expose the Nginx pod as a LoadBalancer service using the below manifest file
$ cat nginx-loadbalancer.yml apiVersion: v1 kind: Service metadata: labels: run: nginx name: nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer
$ kubectl apply -f nginx-loadbalancer.yml service/nginx created
- Check the created nginx service and we can see an IP address in the EXTERNAL-IP section
$ kubectl get svc nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx LoadBalancer 10.96.43.161 172.18.255.200 80:30433/TCP 30s
- Access the application using external IP and port
$ curl http://172.18.255.200:80 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
Cleanup
- Delete the cluster after use
$ kind delete cluster --name dev Deleting cluster "dev" ... Deleted nodes: ["dev-worker2" "dev-control-plane" "dev-worker"]
Top comments (0)