MetalLB Bare Metal Load Balancer
Deploy MetalLB for LoadBalancer services on bare-metal Kubernetes. L2 mode, BGP mode, IP address pools, and integration with Cilium and Gateway API.
π‘ Quick Answer: Install MetalLB and configure an
IPAddressPoolwith your available IPs. Choose L2 mode for simple setups (ARP-based, single node handles traffic) or BGP mode for production (announces routes to your network router, true load distribution).
The Problem
On bare-metal Kubernetes, type: LoadBalancer Services stay in Pending forever β thereβs no cloud provider to create a load balancer. MetalLB fills this gap, providing LoadBalancer IP allocation for bare-metal, on-premises, and homelab clusters.
The Solution
Install MetalLB
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb --namespace metallb-system --create-namespaceL2 Mode (Simple)
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: production-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.220
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: production
namespace: metallb-system
spec:
ipAddressPools:
- production-poolBGP Mode (Production)
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: router
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64501
peerAddress: 192.168.1.1
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: production
namespace: metallb-system
spec:
ipAddressPools:
- production-pool
peers:
- routerUse LoadBalancer Service
apiVersion: v1
kind: Service
metadata:
name: web-app
annotations:
metallb.universe.tf/address-pool: production-pool
spec:
type: LoadBalancer
selector:
app: web-app
ports:
- port: 80
targetPort: 8080graph TD
subgraph L2 Mode
CLIENT1[Client] -->|ARP| LEADER[Leader Node<br/>handles all traffic]
LEADER --> POD1[Pod 1]
LEADER --> POD2[Pod 2]
end
subgraph BGP Mode
CLIENT2[Client] -->|BGP routes| ROUTER[Network Router]
ROUTER --> N1[Node 1 β Pod A]
ROUTER --> N2[Node 2 β Pod B]
ROUTER --> N3[Node 3 β Pod C]
endCommon Issues
Service still Pending after MetalLB install: Check IP pool has available addresses: kubectl get ipaddresspool -n metallb-system. Ensure the IP range is on the same subnet as your nodes (L2 mode).
L2 mode: all traffic goes to one node: Expected behavior. L2 mode uses ARP β one node handles all traffic. For true load distribution, use BGP mode.
Best Practices
- L2 for homelab/dev β simple, no router config needed
- BGP for production β true load distribution across nodes
- Separate pools for different service tiers
- Donβt overlap pools with DHCP range β causes IP conflicts
- Cilium can replace MetalLB β if already using Cilium, use its LB IPAM
Key Takeaways
- MetalLB provides LoadBalancer Services on bare-metal Kubernetes
- L2 mode is simple (ARP) but sends all traffic through one node
- BGP mode distributes traffic across nodes via router integration
- IPAddressPool defines available IPs; Advertisement controls how theyβre announced
- Essential for on-premises, homelab, and edge Kubernetes deployments

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
