kind - Setting up Load Balancer using MetalLB - Part 6
Tags: opensource, docker, kubernetes, devops
Published: 2023-05-03 07:37:23

> 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
    

```bash
$ cat kind.yml 
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: dev
nodes:
- role: control-plane
- role: worker
- role: worker
```

```bash
$ 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
```

```bash
$ 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
    

```bash
$ 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
```

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

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

```bash
$ 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
```

```bash
$ kubectl apply -f metallb.yml 
ipaddresspool.metallb.io/kind unchanged
l2advertisement.metallb.io/kind created
```

```bash
$ 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
    

```bash
$ cat nginx.yml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    ports:
    - containerPort: 80
```

```bash
$ kubectl apply -f nginx.yml 
pod/nginx created
```

```bash
$ 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
    

```bash
$ 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
```

```bash
$ 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
    

```bash
$ 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
    

```bash
$ 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
    

```bash
$ kind delete cluster --name dev
Deleting cluster "dev" ...
Deleted nodes: ["dev-worker2" "dev-control-plane" "dev-worker"]
```

## Reference

[https://kind.sigs.k8s.io/](https://kind.sigs.k8s.io/%EF%BF%BChttps://metallb.universe.tf/)  
[  
https://metallb.universe.tf/](https://kind.sigs.k8s.io/%EF%BF%BChttps://metallb.universe.tf/)