Annoncer les IP de Service avec BGP
Pas de répartiteur de charge cloud ? Cilium peut annoncer les IP de Service directement à votre réseau physique via BGP.
Le type de Service LoadBalancer d’un fournisseur cloud fonctionne parce que le cloud dispose d’une API pour provisionner un répartiteur de charge externe à la demande. Sur du bare metal, ou dans tout environnement sans cette API, un Service LoadBalancer reste indéfiniment en Pending tant que quelque chose d’autre ne remplit pas ce rôle. Le plan de contrôle BGP de Cilium est une façon de le faire : il route l’IP d’un Service directement dans votre réseau physique, en faisant dialoguer en BGP les nœuds du cluster avec les routeurs en amont. Ce guide présente les quatre ressources qui le configurent, et comment vérifier qu’une session BGP est réellement établie des deux côtés.
Quand BGP est le bon outil
Le peering BGP entre des nœuds de cluster et des routeurs en amont est une véritable intégration réseau : elle demande de se coordonner avec les personnes qui gèrent le réseau physique (ou virtuel), une configuration côté routeur qui correspond à votre configuration de peer côté Kubernetes, et une réelle familiarité opérationnelle avec les concepts BGP comme les systèmes autonomes et l’annonce de routes. C’est le bon outil pour un cluster on-premises ou bare metal dont les IP de Service doivent être réellement routables depuis le reste de votre réseau, comme le ferait un LoadBalancer cloud. Pour des besoins plus simples, la fonctionnalité d’annonces L2 de Cilium (annoncer l’IP d’un Service via ARP/NDP sur le segment réseau local, sans protocole de routage) est une alternative plus légère à envisager en premier si votre cluster vit sur un seul segment réseau et n’a pas besoin de routage de couche 3 entre segments ou datacenters.
Les quatre ressources
Quatre ressources personnalisées CiliumBGP* fonctionnent ensemble :
CiliumLoadBalancerIPPooldéfinit une plage d’adresses IP que Cilium peut attribuer aux ServicesLoadBalancer.CiliumBGPAdvertisementdéfinit ce qui est annoncé via BGP, ici les IP de Service tirées de ce pool.CiliumBGPPeerConfigdéfinit comment dialoguer en BGP : timers, comportement de graceful restart, familles d’adresses.CiliumBGPClusterConfigassemble le tout : quels nœuds participent (via un sélecteur de labels), leur numéro d’AS local, et à quels pairs en amont (par IP et numéro d’AS) ils se connectent.
Définir le pool d’IP
apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: apps-pool
spec:
allowFirstLastIPs: "No"
blocks:
- cidr: "10.10.211.0/24"
allowFirstLastIPs: "No" exclut les adresses de réseau et de broadcast (.0 et .255) de la plage attribuable, une convention courante héritée de l’allocation traditionnelle de sous-réseaux. Adaptez le CIDR à la plage que votre équipe réseau vous a réellement allouée pour cet usage ; il doit s’agir d’un espace d’adressage réel et routable de leur point de vue, pas d’une plage privée arbitraire choisie sans concertation.
Définir ce qui est annoncé
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPAdvertisement
metadata:
name: bgp-advertisements
labels:
advertise: bgp
spec:
advertisements:
- advertisementType: Service
service:
addresses:
- LoadBalancerIP
selector:
matchExpressions:
- key: io.kubernetes.service.namespace
operator: Exists
Ceci annonce la LoadBalancerIP des Services correspondants. Le champ labels ici (advertise: bgp) est ce que la configuration de peer ci-dessous référence pour relier les deux, et non un label sur les Services eux-mêmes.
Définir le comportement des pairs
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPPeerConfig
metadata:
name: bgp-peer-config
spec:
timers:
holdTimeSeconds: 9
keepAliveTimeSeconds: 3
gracefulRestart:
enabled: true
restartTimeSeconds: 15
families:
- afi: ipv4
safi: unicast
advertisements:
matchLabels:
advertise: bgp
Le families.advertisements.matchLabels ici relie cette configuration de peer à la ressource d’annonce définie plus haut, en faisant correspondre son label.
Tout assembler : configuration du cluster et sélection des nœuds
apiVersion: cilium.io/v2alpha1
kind: CiliumBGPClusterConfig
metadata:
name: bgp-cluster-config
spec:
nodeSelector:
matchLabels:
role: bgp-node
bgpInstances:
- name: instance-1
localASN: 65011
peers:
- name: leaf-switch-1a
peerASN: 65002
peerAddress: "10.10.210.2"
peerConfigRef:
name: bgp-peer-config
- name: leaf-switch-1b
peerASN: 65002
peerAddress: "10.10.210.3"
peerConfigRef:
name: bgp-peer-config
nodeSelector limite le peering BGP à un sous-ensemble délibéré de nœuds, ceux labellisés role: bgp-node, plutôt que de laisser chaque nœud du cluster tenter de dialoguer avec les routeurs en amont :
kubectl label node worker-4 worker-5 worker-6 role=bgp-node
Une plage raisonnable est de deux à huit nœuds de peering : assez pour éviter un point de défaillance unique, sans obliger votre équipe réseau à configurer et maintenir des sessions BGP vers chaque nœud d’un cluster qui peut en compter des dizaines ou des centaines. Le nombre adéquat dépend de la disposition physique de votre cluster : s’il s’étend sur plusieurs racks ou rangées, il est généralement préférable de faire le peering depuis des nœuds de chacun, plutôt que de concentrer toutes les sessions BGP au même endroit.
Appliquez les quatre ressources, puis vérifiez du côté Kubernetes :
kubectl apply -f bgp-pool.yaml -f bgp-advertisement.yaml -f bgp-peer-config.yaml -f bgp-cluster-config.yaml
Vérifier que la session est bien établie
Du point de vue d’un nœud, en utilisant la CLI de debug propre à Cilium dans le Pod Cilium qui s’exécute sur un nœud labellisé BGP :
kubectl -n kube-system exec <cilium-pod-on-bgp-node> -- cilium-dbg bgp peers
Cherchez un état de session established. Tout autre état (idle, connect, active) signifie que la session n’est pas réellement établie ; les causes les plus courantes sont une incohérence de numéro d’AS entre les deux côtés, une adresse de pair injoignable, ou le routeur en amont qui n’est simplement pas encore configuré pour attendre ce pair. Confirmez que la configuration du pair côté réseau correspond exactement à ce que vous avez déclaré ici avant de supposer que la configuration côté Kubernetes est fautive.
Confirmer qu’une adresse est bien annoncée
Créez un Service LoadBalancer qui puise dans le pool :
kubectl get svc -o wide
Son EXTERNAL-IP doit être une adresse du CIDR du pool. Depuis le routeur en amont (ou depuis ce qui se trouve au-delà : un pare-feu, un routeur de cœur), vérifiez que cette adresse apparaît comme une route /32 apprise via BGP, annoncée depuis les adresses des nœuds de peering. Voir apparaître cette /32 précise, et atteindre avec succès le Service par ce biais, est la véritable confirmation de bout en bout que l’allocation du pool d’IP, l’annonce BGP et le routage propre du réseau physique sont tous correctement reliés, et pas seulement que les ressources côté Kubernetes se sont appliquées sans erreur.
Guides populaires
-
Comment Cilium utilise eBPF : identité, politique et sockets Ce qui se passe réellement dans le noyau quand un Pod démarre, communique avec un autre Pod ou fait l'objet d'une décision de politique sur un paquet, et pourquoi c'est rapide. -
Préparer un cluster pour Cilium : désactiver d'abord le CNI par défaut Cilium remplace entièrement le réseau de votre cluster, ce qui rend l'ordre des opérations plus important qu'avec la plupart des add-ons. -
Exposer des Services avec la prise en charge de Gateway API de Cilium GatewayClass, Gateway et HTTPRoute : routage par nom d'hôte, correspondance de chemins, réécriture d'URL et TLS, sans Pods de passerelle dédiés. -
Écrire des politiques réseau : des règles L3/L4 aux règles L7 Kubernetes part du principe que chaque Pod peut joindre tous les autres Pods ; CiliumNetworkPolicy permet de restreindre cela, jusqu'à la méthode HTTP si nécessaire.