Automatically set MetalLB IP Addresses with kind

09 Jul 2023 in TIL

kind doesn't come with a Load Balancer implementation by default. MetalLB seems like the most commonly used load balancer, but I have to look up how to configure it every time.

That is, until I saw an awesome docker network inspect | yq hack that I'm adding here for posterity.

First, install MetalLB:

bash
kubectl apply -f \
https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml

Then extract the subnet from the kind network and use yq to set the spec.addresses value in the manifest before applying it:

js
echo "---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: demo-pool
namespace: metallb-system
spec:
addresses: [] # set by make target
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: demo-advertisement
namespace: metallb-system
spec:
ipAddressPools:
- demo-pool
" | \
SUBNET=$(docker network inspect kind --format '{{ (index .IPAM.Config 0).Subnet }}' | sed 's#0/24#100/27#') \
kubectl apply -f -

That's all! For a few more details, here's what gets returned by docker network inspect:

bash
❯ docker network inspect kind --format '{{ (index .IPAM.Config 0).Subnet }}'
192.168.207.0/24

The sed command ensures that we don't issue an IP that conflicts with reserved IPs by switching the CIDR to 192.168.207.100/27, which is IPs in the range 192.168.207.96-192.168.207.127

And if I run kubectl get services we'll see an IP address of 192.168.207.96 which is in that range:

bash
❯ kubectl get services -n kong
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kong-controller-validation-webhook ClusterIP 10.96.172.187 <none> 443/TCP 3m31s
kong-gateway-admin ClusterIP None <none> 8444/TCP 3m31s
kong-gateway-manager NodePort 10.96.43.132 <none> 8002:32453/TCP,8445:30348/TCP 3m31s
kong-gateway-proxy LoadBalancer 10.96.27.232 192.168.207.96 80:32599/TCP,443:32760/TCP 3m31s