MetalLB gives a Kubernetes cluster that runs on bare metal, or on any network without a cloud provider’s load balancer, a working implementation of Service type LoadBalancer. Without it, such a service stays in the pending state because nothing exists to hand out an external address. MetalLB takes addresses from pools the administrator defines, assigns one to each service, and makes the network deliver that address’s traffic to the cluster, using either ARP and NDP at Layer 2 or BGP sessions with nearby routers. The project began as an independent open source effort and was accepted into the CNCF Sandbox on September 14, 2021.
CNCF daily · Sprint 3, post 9 of 21 · Service Proxy
At a glance
| Category | Orchestration & Management › Service Proxy |
| CNCF status | Sandbox. Accepted September 14, 2021 |
| Written in | Go |
| License | Apache 2.0 |
| Core resources | IPAddressPool, L2Advertisement, BGPAdvertisement, BGPPeer |
| Modes | Layer 2 (ARP for IPv4, NDP for IPv6) and BGP |
| Components | A cluster-wide controller that assigns addresses, and a speaker on every node that announces them |
| Install options | Manifests, Helm chart and Kustomize into the metallb-system namespace |
Architecture
Slate is Kubernetes and the network, purple the MetalLB components, grey the cluster data path and blue the client. MetalLB appears only on the control and announcement side; packets never pass through it. Open the zoomable diagram, or download it as SVG or PNG.
| Component | Responsibility |
|---|---|
| Kubernetes API | Holds the Service objects and the MetalLB resources: IPAddressPool, L2Advertisement, BGPAdvertisement and BGPPeer. |
| Controller | Watches services of type LoadBalancer, assigns each an address from an IPAddressPool, and records it in the service status. |
| Speaker | Runs on each node, watches the same objects, and announces assigned addresses to the network by answering ARP or NDP requests or by speaking BGP. |
| Switch or router | Learns where the address lives and forwards the client’s packets to the announcing node. |
| Node, kube-proxy or CNI | Receives the packets and steers them to a backend pod. |
Design principle. MetalLB does not forward traffic itself. It only gets traffic for an address to a node. From there, kube-proxy or the CNI plugin steers packets to pods, so MetalLB composes with the existing data path rather than replacing it.
From a pending Service to a packet in a pod
- Watch. The controller sees a new
Serviceof typeLoadBalancerand theIPAddressPoolit may draw from. - Assign. It picks a free address from the pool and writes it to the service status, so the service stops showing
pending. - Notice. The speakers, watching the same Service and the advertisement resources, see the assigned address.
- Announce. In Layer 2 mode one speaker answers ARP or NDP requests for the address; in BGP mode the speakers advertise a route to the upstream router.
- Send. A client on the network sends packets to the service address.
- Deliver. The switch or router forwards them to the announcing node.
- Forward. kube-proxy or the CNI plugin on the node sends the packets to a backend pod.
Steps 1 to 4 happen once for each service; steps 5 to 7 happen for every connection.
Open the zoomable flow diagram, or download it as SVG or PNG.
Production reference design
A typical edge or on-premises site has three or more nodes and a router or switch pair that the team controls.
- Prepare the cluster. If kube-proxy runs in IPVS mode, enable strict ARP in its configuration, as the MetalLB documentation requires. If the cluster enforces Pod Security Admission, label the
metallb-systemnamespace as privileged, because the speaker needs elevated network privileges. - Install MetalLB with Helm, pinning a stable release rather than a development branch:
helm repo add metallb https://metallb.github.io/metallb helm install metallb metallb/metallb --namespace metallb-system --create-namespace - Define the address pool and the announcement. A Layer 2 example for a small site, with addresses reserved outside the DHCP range:
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: { name: edge-pool, namespace: metallb-system } spec: addresses: ["192.168.10.240-192.168.10.250"] --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: { name: edge-l2, namespace: metallb-system } spec: ipAddressPools: ["edge-pool"] - Expose a service. Create a
Serviceof typeLoadBalancerand confirm that an external address appears in its status, then request it from another machine on the same network. - Move to BGP when needed. Define a
BGPPeerfor the upstream router and aBGPAdvertisementfor the pool, so that every node can attract traffic and the router balances across them. Add BFD where fast failure detection matters.
Typical uses include exposing an ingress controller or gateway on bare-metal clusters, providing stable addresses at edge sites, and giving each cluster in a multi-site design a predictable entry point that a global load balancer such as k8gb can publish through DNS.
Operational considerations
- Layer 2 mode has one active node per address. All traffic for a service enters through a single node, which limits bandwidth to that node and makes failover depend on a new node taking over the address. It needs no router configuration and suits small sites.
- BGP mode spreads traffic across nodes. It needs routers that accept peering from the nodes, and the split depends on the router’s hashing. Existing connections can be disrupted when the set of announcing nodes changes, so plan maintenance accordingly.
- Plan the address ranges. Keep pools outside DHCP ranges and ensure they do not overlap across sites that later interconnect. Editing or deleting a pool can cause assigned addresses to change.
- Check CNI compatibility. Some network plugins also speak BGP or manage the same addresses. Read the compatibility notes for your CNI before enabling BGP mode.
- Secure and observe. The speaker runs privileged, so restrict who can edit the MetalLB resources. Scrape the controller and speaker metrics and alert on services stuck without an address.
Adoption
- MetalLB is widely used on bare-metal and edge clusters, and several Kubernetes distributions document it as their recommended on-premises load-balancer add-on.
- The repository keeps an
ADOPTERS.mdfile where users list themselves. Consult it for current named organisations rather than relying on a fixed list here. - Because the project is at the Sandbox level, treat the CNCF label as an early stage and evaluate its release cadence and issue activity directly.
Alternatives
| Solution | Model | Best suited to |
|---|---|---|
| kube-vip (CNCF Sandbox) | Virtual IP for the control plane and services | Small clusters that also need a highly available API server address |
| Cilium (CNCF Graduated) | Built-in load-balancer IP management and BGP control plane | Clusters already on Cilium that prefer fewer components; see the Cilium brief |
| LoxiLB (CNCF Sandbox) | eBPF-based service load balancer | Edge and telco setups needing high-performance Layer 4 balancing |
| Cloud load balancers | Provider-managed through the cloud controller | Clusters inside a public cloud, where MetalLB is not needed |
| Hardware or external appliances | Dedicated load balancers in front of node ports | Sites with an existing appliance team and fixed procedures |
Strengths and limitations
| Strengths | Limitations |
|---|---|
Brings LoadBalancer services to any bare-metal cluster |
Layer 2 mode sends each address’s traffic through one node |
| Uses standard protocols, with no vendor hardware | BGP mode needs routers that accept peering and careful configuration |
| Declarative configuration through Kubernetes resources | Does not terminate TLS or route by host, so it pairs with an ingress or gateway |
| Works with existing kube-proxy and CNI data paths | Some CNIs conflict in BGP mode |
| Apache 2.0 licence and a long track record on bare metal | Sandbox maturity; some alternatives are bundled with the CNI |
Recommendation
Adopt for bare-metal and edge Kubernetes clusters that need LoadBalancer services and do not already get this from the CNI. Start in Layer 2 mode on a small site to validate address ranges and failover, and move to BGP where traffic volume or fast convergence matter. Clusters on a public cloud should keep the provider’s load balancer, and clusters that already run Cilium with its own load-balancer features should weigh using that instead of adding another component.
References: CNCF project page · MetalLB documentation · MetalLB installation guide · MetalLB repository · CNCF Landscape

