Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

DevOps · CNCF daily

MetalLB: Load-Balancer Services for Bare-Metal Kubernetes Clusters

CNCF Sandbox. A network load-balancer implementation for Kubernetes that assigns external addresses to LoadBalancer services and announces them with standard Layer 2 or BGP protocols, so clusters outside a cloud get the same service type as clusters inside one.

7 min read

CNCF Sandbox

  • MetalLB
  • Kubernetes
  • BGP
  • Envoy
  • k8gb
CNCF project page

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

flowchart TB
  CLIENT[Client<br/>on the site network] ==>|1 packets to service IP| NET[Switch or router]
  NET ==>|2 delivered to announcing node| NODE[Cluster node<br/>kube-proxy or CNI]
  NODE ==>|3 forwarded to a pod| POD[Backend pod]
  USER[Service of type<br/>LoadBalancer] -.->|watched by| CTRL[MetalLB controller]
  POOL[IPAddressPool] -.->|address ranges| CTRL
  CTRL -.->|assigns external IP<br/>writes service status| USER
  SPK[MetalLB speaker<br/>on every node] -.->|reads assignments| CTRL
  SPK ==>|ARP and NDP replies<br/>in Layer 2 mode| NET
  SPK ==>|BGP routes<br/>in BGP mode| NET
  classDef core fill:#0f766e,stroke:#064e4a,stroke-width:2px,color:#ffffff
  classDef data fill:#e3f2fd,stroke:#1565c0,stroke-width:1.5px,color:#1d1c1a
  classDef actor fill:#eceff1,stroke:#455a64,stroke-width:1.5px,color:#1d1c1a
  classDef cfg fill:#ede7f6,stroke:#5e35b1,stroke-width:1.5px,color:#1d1c1a
  class CTRL,SPK core
  class NODE,POD,NET data
  class CLIENT actor
  class USER,POOL cfg

Key: teal blocks are MetalLB components, blue are the network and the cluster data path, purple are Kubernetes and MetalLB configuration, grey is the client. Numbers follow a packet; thick arrows carry traffic and announcements, dashed arrows carry control information.

Component Responsibility
Controller Watches services of type LoadBalancer and assigns each an address from an IPAddressPool, then records it in the service status.
Speaker Runs on each node and announces assigned addresses to the network, by answering ARP or NDP requests or by speaking BGP.
IPAddressPool Declares the address ranges MetalLB may use and which services may draw from each range.
L2Advertisement / BGPAdvertisement Choose how a pool is announced, and limit the announcement to chosen nodes or interfaces.
BGPPeer Describes a router that nodes peer with, including its address and autonomous system number.

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.

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.

  1. 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-system namespace as privileged, because the speaker needs elevated network privileges.
  2. 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
  3. 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"]
  4. Expose a service. Create a Service of type LoadBalancer and confirm that an external address appears in its status, then request it from another machine on the same network.
  5. Move to BGP when needed. Define a BGPPeer for the upstream router and a BGPAdvertisement for 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.md file 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

Spotted something wrong or out of date?Suggest a correction. I review every suggestion before changing the page.