Advertisements don't have to be one-size-fits-all. This episode dissects advanced L2Advertisement options like interfaces and nodeSelectors, BGPAdvertisement options like communities, aggregationLength and localPref, plus using multiple advertisements at once.

So far, the advertisements we've created are the simplest kind: one advertisement for one pool. Episode 8 shows that advertisements can be finely customized to meet varied network needs — restricting which nodes may announce, choosing specific network interfaces, or embedding BGP attributes that influence routing decisions on external routers.
This customization isn't just a nice extra feature. On complex networks — say, a cluster with internal and public segments, or a company enforcing specific routing policies — this capability is often the difference between an acceptable solution and an unusable one.
By default, the speaker announces via all non-loopback interfaces on a node. The interfaces option restricts announcements to specific interfaces only. This is useful when a node has many interfaces and you only want to announce on a particular network segment:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-internal
namespace: metallb-system
spec:
ipAddressPools:
- internal-pool
interfaces:
- eth1With interfaces: eth1, IPs from internal-pool are only announced via the eth1 interface. If an interface isn't available on a node, that node won't announce the IP — so announcements automatically only happen on nodes that have the interface.
The nodeSelectors option uses node labels to determine which nodes may announce. The following example restricts announcements to nodes labeled network-zone: dmz:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-dmz
namespace: metallb-system
spec:
ipAddressPools:
- dmz-pool
nodeSelectors:
- matchLabels:
network-zone: dmznodeSelectors: matchLabels: network-zone: dmz ensures IPs from dmz-pool are only announced by nodes in the DMZ zone. Combining interfaces and nodeSelectors gives you very precise control over the announcement topology.
BGP communities are labels attached to the routes you advertise. External routers can use the community to apply policy — for example, preventing a route from being advertised further, or marking a route as internal. The value 65535:65282, for instance, represents the well-known community NO_ADVERTISE:
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-tagged
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
communities:
- "65535:65282"With communities: "65535:65282", all routes from this pool are tagged NO_ADVERTISE — routers that receive them won't forward the routes to other peers. How to create named communities (via the Community CRD) and advanced scenarios are covered in episode 16.
By default, each Service IP is advertised as a separate /32 (IPv4) route. aggregationLength makes MetalLB combine several adjacent IPs into a single shorter prefix, so the router's routing table doesn't bloat:
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-aggregated
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
aggregationLength: 24With aggregationLength: 24, Service IPs that fall within the same /24 subnet are advertised as a single 192.168.1.0/24 route. The trade-off: if a Service isn't active within the prefix, traffic to that IP can enter the cluster and then be dropped — so aggregation aggressiveness needs planning (details in episode 17).
localPref affects the local preference value of the routes advertised to the router. Routes with a higher localPref are preferred by the router when choosing a path:
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-primary
namespace: metallb-system
spec:
ipAddressPools:
- primary-pool
localPref: 150localPref: 150 gives routes from primary-pool a preference value of 150 (above the default of 100). On networks with multiple paths, this is a mechanism to prioritize one pool over another — episode 16 will cover combining it with communities.
MetalLB allows more than one advertisement for the same pool. The most common examples: advertising the same pool to two different BGP peers with different attributes, or combining L2 and BGP for different needs.
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-core
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
peers:
- core-router
aggregationLength: 24
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-edge
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
peers:
- edge-router
localPref: 120These two advertisements advertise the same pool with different behavior per peer. Verify all active advertisements:
kubectl get l2advertisement
kubectl get bgpadvertisement
kubectl get bgpadvertisement bgp-core -o yamlkubectl get bgpadvertisement bgp-core -o yaml shows full details, including how peers and aggregation options are presented in the status. This is the best way to confirm the customization has been applied as intended.
Episode 8 completes advertisement customization: interfaces and nodeSelectors to control Layer 2 announcements, communities, aggregationLength, and localPref to influence router decisions in BGP mode, plus using multiple advertisements for a single pool.
Key takeaways:
interfaces restricts L2 announcements to specific interfaces.nodeSelectors restricts L2 announcements to nodes with specific labels.communities attach tags to advertised routes.aggregationLength combines prefixes to shrink the routing table.localPref prioritizes one route over another in the eyes of routers.In the next episode, episode 9, we'll discuss multi-pool & traffic policies — separating pools per dev and prod environment, using serviceAllocation or annotations to pick a pool per Service, and understanding the impact of externalTrafficPolicy: Local versus Cluster on source IPs and failover.