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.

8 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

MetalLB architecture: the controller watches Services of type LoadBalancer and IPAddressPools in the Kubernetes API and writes the assigned external IP to the Service status; the speaker on each node watches the same objects and announces the address to the switch or router with ARP, NDP or BGP; client packets reach the announcing node, where kube-proxy or the CNI forwards them to a backend pod

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

MetalLB flow in seven steps: the controller sees a LoadBalancer Service and a pool, writes the external IP to the Service status, the speaker sees the assignment and announces it to the router, a client sends packets to the service IP, the router delivers them to the announcing node, and kube-proxy or the CNI forwards them to a backend pod

  1. Watch. The controller sees a new Service of type LoadBalancer and the IPAddressPool it may draw from.
  2. Assign. It picks a free address from the pool and writes it to the service status, so the service stops showing pending.
  3. Notice. The speakers, watching the same Service and the advertisement resources, see the assigned address.
  4. 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.
  5. Send. A client on the network sends packets to the service address.
  6. Deliver. The switch or router forwards them to the announcing node.
  7. 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.

  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.