Check the address pool¶
kubectl get ipaddresspools.metallb.io -n metallb
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
default-pool true false ["10.0.0.100-10.0.0.200"]
AUTO ASSIGN true means MetalLB assigns from this pool to any LoadBalancer service that doesn't ask for a specific pool. If a service isn't getting an IP:
kubectl get l2advertisements.metallb.io -n metallb # must exist, or nothing is announced
kubectl describe svc <service> # MetalLB posts allocation events here
kubectl logs -n metallb deploy/metallb-controller
Node reports the wrong IP (Calico tunl0)¶
Symptom¶
kubectl get pods -n metallb -o wide
NAME READY STATUS IP NODE
metallb-controller-7bd5848b94-c826n 1/1 Running 10.244.158.207 cluster1
metallb-speaker-22l62 4/4 Running 10.0.0.10 cluster0
metallb-speaker-4vvsw 4/4 Running 10.0.0.12 cluster2
metallb-speaker-zq25m 4/4 Running 10.0.0.11 cluster1
The controller's 10.244.x.x address is expected. The controller is an ordinary pod and gets a pod-network IP. The speakers run with hostNetwork: true, so they should show each node's LAN address, as they do here.
The real thing to check is the node's own reported address:
kubectl get nodes -o wide
If a node's INTERNAL-IP is wrong, or Calico picked the wrong interface for the node, the speaker announces from the wrong place and the service IPs are unreachable. On that node, Calico's IPIP tunnel interface carries an address from the pod range:
ip a s tunl0
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
inet 10.244.158.192/32 scope global tunl0
Fix¶
1. Pin the kubelet's node IP to the LAN address. Use /etc/default/kubelet on Debian/Ubuntu and /etc/sysconfig/kubelet on RHEL/Alma:
KUBELET_EXTRA_ARGS=--node-ip=10.0.0.11
sudo systemctl daemon-reload
sudo systemctl restart kubelet
kubectl get node cluster1 -o wide # INTERNAL-IP should now be the LAN address
2. Pin Calico's address autodetection so it doesn't choose the wrong interface on multi-NIC hosts. In the operator's Installation resource:
kubectl edit installation default
spec:
calicoNetwork:
nodeAddressAutodetectionV4:
kubernetes: NodeInternalIP # follow the kubelet's --node-ip
# or: interface: "eth0" / canReach: 10.0.0.1
For the other known Calico/MetalLB interactions, see https://metallb.universe.tf/configuration/calico/
Restart MetalLB¶
Use this after a config change that isn't being picked up, or to clear a stuck speaker:
kubectl rollout restart deployment metallb-controller -n metallb
kubectl rollout restart daemonset metallb-speaker -n metallb
kubectl get pods -n metallb -w
Alternatively, delete the pods outright. The Deployment and DaemonSet recreate them:
kubectl delete pods -n metallb -l app.kubernetes.io/name=metallb
If a speaker keeps crash-looping, read the crashed instance's logs before restarting it again:
kubectl logs -n metallb -l app.kubernetes.io/component=speaker --previous