By default, BGP mode advertises each allocated IP to the configured
peers with no additional BGP attributes. The peer router(s) will
/32 route for each service IP, with the BGP localpref
set to zero and no BGP communities.
You can configure more elaborate advertisements with multiple
that lists one or more custom advertisements.
In addition to specifying localpref and communities, you can use this
to advertise aggregate routes. The
option lets you “roll up” the /32s into a larger prefix. Combined with
multiple advertisement configurations, this lets you create elaborate
advertisements that interoperate with the rest of your BGP network.
For example, let’s say you have a leased
/24 of public IP space, and
you’ve allocated it to MetalLB. By default, MetalLB will advertise
each IP as a /32, but your transit provider rejects routes more
/24. So, you need to somehow advertise a
/24 to your
transit provider, but still have the ability to do per-IP routing
Here’s a configuration that implements this:
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 198.51.100.10/24
apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: local spec: ipAddressPools: - first-pool aggregationLength: 32 localpref: 100 communities: - 65535:65282
apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: external spec: ipAddressPools: - first-pool aggregationLength: 24
With this configuration, if we create a service with IP 198.51.100.10, the BGP peer(s) will receive two routes:
198.51.100.10/32, with localpref=100 and the
no-advertisecommunity, which tells the peer router(s) that they can use this route, but they shouldn’t tell anyone else about it.
198.51.100.0/24, with no custom attributes.
With this configuration, the peer(s) will propagate the
198.51.100.0/24 route to your transit provider, but once traffic
shows up locally, the
198.51.100.10/32 route will be used to forward
into your cluster.
As you define more services, the router will receive one “local”
for each of them, as well as the covering
/24. Each service you
define “generates” the
/24 route, but MetalLB deduplicates them all
down to one BGP advertisement before talking to its peers.
Additionally, we can define community aliases in order to have descriptive names for the communities, to be used in place of the two 16 bits format.
By default, every node in the cluster connects to all the peers listed in the configuration. In more advanced cluster topologies, you may want each machine to peer with its top-of-rack router, but not the routers in other racks. For example, if you have a “rack and spine” network topology, you likely want each machine to peer with its top-of-rack router, but not the routers in other racks.
You can limit peers to certain nodes by using the
attribute of peers in the configuration. The semantics of these
selectors are the same as those used elsewhere in Kubernetes, so refer
to the labels documentation on
the Kubernetes website.
For example, this is a (somewhat contrived) definition for a peer that will only be used by machines:
rack=frontendlabel, but not the label
apiVersion: metallb.io/v1beta2 kind: BGPPeer metadata: name: example namespace: metallb-system spec: myASN: 64512 peerASN: 64512 peerAddress: 172.30.0.3 peerPort: 180 nodeSelectors: - matchLabels: rack: frontend matchExpressions: - key: network-speed operator: NotIn values: [slow] - matchExpressions: - key: kubernetes.io/hostname operator: In values: [hostA, hostB]
It is possible to limit the set of nodes that are advertised as next hops to reach
the service IPs. This is achieved by using the node selector in the
In this example, the service is announced only from NodeA and NodeB.
Note that this feature is orthogonal to the BGP peer node selector,
as it’s performed at service (
MetalLB will still follow the
to choose if a certain node must be peered with a certain router.
In order to limit the set of nodes for a given advertisement, the node selector must be set:
apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: example spec: ipAddressPools: - first-pool nodeSelectors: - matchLabels: kubernetes.io/hostname: NodeA - matchLabels: kubernetes.io/hostname: NodeB
In this way, all the IPs coming from
first-pool will be reacheable only via
By default, every service IP is advertised to all the connected peers. It is possible
to limit the set of peers a service IP is advertised to. This is achieved by using
the peers in the
In this example, a service IP from PoolA is announced only to PeerA and PeerB, while a service IP from PoolB is announced only to PeerB and PeerC.
In order to limit the set of peers for a given advertisement, the peers must be set:
apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: example spec: ipAddressPools: - PoolA peers: - PeerA - PeerB
In this way, all the IPs coming from
PoolA will be advertised only to
When a host has multiple network interfaces or multiple IP addresses configured on one interface, the host’s TCP/IP stack usually selects the IP address that is used as the source IP address for outbound connections automatically. This is true also for BGP connections.
Sometimes, the automatically-selected address may not be the desired one for some reason. In such cases, MetalLB supports explicitly specifying the source address to be used when establishing a BGP session:
apiVersion: metallb.io/v1beta2 kind: BGPPeer metadata: name: example namespace: metallb-system spec: myASN: 64512 peerASN: 64512 peerAddress: 172.30.0.3 peerPort: 179 sourceAddress: 172.30.0.2 nodeSelectors: - matchLabels: kubernetes.io/hostname: node-1
The configuration above tells the MetalLB speaker to check if the
172.30.0.2 exists locally on one of the host’s network
interfaces, and if so - to use it as the source address when
establishing BGP sessions. If the address isn’t found, the default
behavior takes place (that is, the kernel selects the source address
In most cases the
source-address field should only be used with
per-node peers, i.e. peers with node selectors which select only
By default, a BGP peer configured under the
section runs on all speaker nodes. It is likely meaningless to use
source-address field in a peer configuration that applies to
more than one node because two nodes in a given network usually
shouldn’t have the same IP address.
It’s possible to define aliases for BGP Communities used when advertising. This is done by using
Community CRD that allows to associate a name to a given BGP community:
apiVersion: metallb.io/v1beta1 kind: Community metadata: name: communities namespace: metallb-system spec: communities: - name: vpn-only value: 1234:1 - name: NO_ADVERTISE value: 65535:65282
After defining an alias, it can be used in the
BGPAdvertisement in place of its
two 16 bits number format:
apiVersion: metallb.io/v1beta1 kind: BGPAdvertisement metadata: name: local spec: ipAddressPools: - first-pool aggregationLength: 32 localpref: 100 communities: - vpn-only