Blog

MetalLB sur OpenShift : LoadBalancer BGP et L2

OpenShift
MetalLB
Réseau
BGP
Bare-metal

Mise en place de MetalLB sur OpenShift pour exposer des services de type LoadBalancer en bare-metal. Comparaison des modes L2 et BGP, configuration des IPAddressPools et intégration avec les routeurs d'entreprise.

10 décembre 2024

Le problème du LoadBalancer en bare-metal

Dans les environnements cloud (AWS, GCP, Azure), les services Kubernetes de type LoadBalancer provisionnent automatiquement un load-balancer cloud avec une IP publique. En bare-metal ou en datacenter privé, ce mécanisme n’existe pas nativement dans OpenShift.

MetalLB résout ce problème en implémentant un contrôleur de LoadBalancer pour les clusters bare-metal. Il attribue des adresses IP aux services LoadBalancer depuis des plages configurées et les annonce sur le réseau via deux modes : Layer 2 (ARP/NDP) ou BGP.


Installation via l’Operator MetalLB

Red Hat maintient un Operator MetalLB certifié pour OpenShift, disponible dans l’OperatorHub.

# Créer le namespace MetalLB
oc create namespace metallb-system

# Installer l'Operator
cat <<EOF | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: metallb-operator
  namespace: metallb-system
spec:
  channel: stable
  name: metallb-operator
  source: redhat-operators
  sourceNamespace: openshift-marketplace
EOF

Ensuite, instancier MetalLB en créant la CR MetalLB :

apiVersion: metallb.io/v1beta1
kind: MetalLB
metadata:
  name: metallb
  namespace: metallb-system
spec:
  nodeSelector:
    node-role.kubernetes.io/worker: ""

Mode Layer 2 (L2)

Le mode L2 est le plus simple à mettre en place. MetalLB désigne un nœud speaker qui répond aux requêtes ARP (IPv4) ou NDP (IPv6) pour les IPs des services LoadBalancer. Tout le trafic passe par ce nœud avant d’être distribué via kube-proxy.

Quand utiliser L2 ?

  • Réseau plat (même sous-réseau L2 entre les nœuds et les clients)
  • Environnements de lab ou petits clusters
  • Pas de routeurs BGP disponibles
  • Bande passante suffisante sur un seul nœud

Configuration L2

# Définir un pool d'adresses IP
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: pool-l2
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.200-192.168.1.250
  autoAssign: true
---
# Activer l'annonce L2 pour ce pool
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: annonce-l2
  namespace: metallb-system
spec:
  ipAddressPools:
    - pool-l2
  # Optionnel : restreindre à certains nœuds
  nodeSelectors:
    - matchLabels:
        kubernetes.io/os: linux

Limitation du mode L2

L’inconvénient majeur est l’absence de distribution de charge réelle : tout le trafic entrant transite par un seul nœud (le speaker actif). En cas de panne, MetalLB bascule automatiquement sur un autre nœud (failover ~10 secondes).


Mode BGP

Le mode BGP (Border Gateway Protocol) est recommandé pour les environnements de production. MetalLB établit des sessions BGP avec les routeurs d’infrastructure et annonce les routes vers les IPs des services LoadBalancer. Le trafic est ainsi distribué directement vers les nœuds par le routeur, offrant une vraie distribution de charge (ECMP).

Prérequis

  • Un ou plusieurs routeurs supportant BGP (Cisco, Juniper, FRRouting, etc.)
  • Des ASN (Autonomous System Numbers) alloués pour MetalLB et les routeurs pairs
  • Connectivité réseau entre les nœuds MetalLB speakers et les routeurs

Architecture BGP typique

Internet / LAN

   Routeur (ASN 65000)
   ├── Peer: node-1 (ASN 65001) → IP 10.0.0.1/32
   ├── Peer: node-2 (ASN 65001) → IP 10.0.0.1/32
   └── Peer: node-3 (ASN 65001) → IP 10.0.0.1/32

Chaque nœud annonce la même IP → le routeur distribue via ECMP.

Configuration BGP

# Pool d'adresses pour BGP
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: pool-bgp
  namespace: metallb-system
spec:
  addresses:
    - 10.0.0.0/24
  autoAssign: true
---
# Définir les pairs BGP (routeurs)
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: routeur-core
  namespace: metallb-system
spec:
  myASN: 65001          # ASN de MetalLB
  peerASN: 65000        # ASN du routeur
  peerAddress: 172.16.0.1
  # Optionnel : restreindre à des nœuds spécifiques
  nodeSelectors:
    - matchLabels:
        node-role.kubernetes.io/worker: ""
---
# Activer l'annonce BGP pour le pool
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: annonce-bgp
  namespace: metallb-system
spec:
  ipAddressPools:
    - pool-bgp
  aggregationLength: 32       # Annonce des /32 par IP
  communities:
    - 65000:100               # Communauté BGP custom

BGP avec BFD (Bidirectional Forwarding Detection)

BFD permet une détection rapide des pannes de liaison (sub-seconde) :

apiVersion: metallb.io/v1beta1
kind: BFDProfile
metadata:
  name: bfd-fast
  namespace: metallb-system
spec:
  receiveInterval: 150    # ms
  transmitInterval: 150   # ms
  detectMultiplier: 3
  echoMode: false
---
# Référencer le profil BFD dans le BGPPeer
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  name: routeur-core-bfd
  namespace: metallb-system
spec:
  myASN: 65001
  peerASN: 65000
  peerAddress: 172.16.0.1
  bfdProfile: bfd-fast

Utiliser un service LoadBalancer

Une fois MetalLB configuré, la création d’un service LoadBalancer est standard :

apiVersion: v1
kind: Service
metadata:
  name: mon-service
  namespace: production
  annotations:
    # Forcer l'utilisation d'un pool spécifique
    metallb.universe.tf/address-pool: pool-bgp
spec:
  type: LoadBalancer
  selector:
    app: mon-app
  ports:
    - port: 443
      targetPort: 8443
      protocol: TCP

Vérifier l’IP attribuée :

oc get svc mon-service -n production
# NAME          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)
# mon-service   LoadBalancer   10.96.45.12     10.0.0.5      443:30042/TCP

Permissions SELinux et SCC sur OpenShift

OpenShift impose des Security Context Constraints (SCC) strictes. Les pods MetalLB speaker ont besoin de capacités réseau spéciales. L’Operator gère automatiquement les SCC nécessaires, mais vérifier :

# Vérifier les SCC appliquées aux speakers
oc get pod -n metallb-system -l component=speaker \
  -o jsonpath='{.items[*].metadata.annotations.openshift\.io/scc}'

Les speakers ont besoin de privileged ou d’une SCC custom permettant NET_RAW et NET_ADMIN.


Comparaison L2 vs BGP

CritèreMode L2Mode BGP
SimplicitéTrès simpleConfiguration réseau requise
Distribution de chargeNon (nœud unique)Oui (ECMP)
Failover~10 secondesSub-seconde avec BFD
ScalabilitéLimitéeHaute
Prérequis réseauAucunRouteurs BGP
Cas d’usageLab, dev, petits clustersProduction, bare-metal entreprise

Conclusion

MetalLB comble un manque critique pour les déploiements OpenShift bare-metal. En mode L2, il est opérationnel en quelques minutes. En mode BGP, il offre une solution de production robuste avec distribution de charge réelle et failover rapide, à condition d’avoir l’infrastructure réseau adaptée.