Déployer Cilium avec un LoadBalancer sur Talos Linux¶
Apprenez à configurer des services LoadBalancer externes sur Kubernetes bare-metal TalosLinux en utilisant Cilium CNI avec des annonces L2.
Ce que vous allez apprendre¶
À la fin de ce tutoriel, vous allez apprendre à :
- Comprendre pourquoi le
LoadBalancer L2est nécessaire sur Kubernetes bare-metal - Installer
Cilium CNIsur Talos Linux avec support des annonces L2 - Configurer les pools d'IP et les politiques d'annonce L2
- Déployer un service LoadBalancer accessible depuis les réseaux externes (LAN)
- Vérifier et debuguer les annonces L2
Durée
Durée estimée: 45-60 minutes
Niveau: Intermédiaire (connaissance de Kubernetes et réseaux recommandée)
Prérequis¶
Avant de commencer, assurez-vous d'avoir :
- Un cluster Talos Linux en cours d'exécution (v1.6+)
-
kubectlconfiguré pour accéder à votre cluster - CLI
helminstallé (v3.0+) - CLI
talosctlinstallé - Compréhension de base des concepts de réseau Kubernetes
- Accès administrateur pour configurer les ressources du cluster
Contexte Talos Linux
Ce tutoriel est spécifiquement écrit pour Talos Linux, un système d'exploitation Kubernetes immuable. Si vous utilisez des distributions Kubernetes standard, certaines étapes seront différentes (surtout l'installation du CNI et la configuration système).
Introduction¶
Le défi du LoadBalancer sur Bare-Metal, Homelab ou Environnements On-Premise¶
Dans les environnements cloud comme AWS, Azure ou GCP, créer un service k8s de type LoadBalancer provisionne automatiquement un load balancer cloud (AWS ELB, Azure Load Balancer, GCP Cloud Load Balancing). Cependant, sur des clusters Kubernetes bare-metal ou homelab, les services LoadBalancer restent en état <pending> car il n'y a pas d'intégration avec un fournisseur cloud.
# Exemple sur un cluster cloud (avec LB-IPAM fonctionnel)
$ kubectl expose deployment nginx --type=LoadBalancer --port=80
$ kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
nginx LoadBalancer 10.43.100.123 203.0.113.45 80:30080/TCP
# Sur bare-metal (sans LB-IPAM)
$ kubectl expose deployment nginx --type=LoadBalancer --port=80
$ kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
nginx LoadBalancer 10.43.100.123 <pending> 80:30080/TCP # ❌ Bloqué!
Solutions : MetalLB vs Cilium LB-IPAM¶
Deux solutions populaires existent pour les services LoadBalancer sur bare-metal :
- MetalLB - Load balancer autonome pour Kubernetes
- Cilium LB-IPAM - Gestion intégrée des adresses IP LoadBalancer dans Cilium le Controller Network Interface CNI de kubernetes.
Précédemment, j'utilisais MetalLB dans mes clusters homelab avec kube-proxy natif. J'ai décidé récemment d'utiliser Cilium comme CNI, utiliser le LB-IPAM intégré de Cilium est donc le choix naturel.
Pourquoi Cilium LB-IPAM ?
- Solution intégrée - Aucun composant supplémentaire nécessaire
- Basé sur eBPF - Hautes performances avec faible overhead
- Support L2 et BGP - Méthodes d'annonce flexibles
- Compatible KubePrism - Fonctionne parfaitement avec Talos
- Géré par Helm - Configuration et mises à jour faciles
Comprendre le duo Talos + Cilium¶
Architecture Talos Linux¶
Talos Linux est différent des distributions Linux traditionnelles :
- OS immuable - Pas de SSH, pas de shell, pas de gestionnaire de paquets
- Piloté par API - Géré via
talosctlet l'API Kubernetes - Sécurisé par défaut - Surface d'attaque minimale
- CGroup v2 - Système de fichiers cgroup Linux moderne
- KubePrism - Proxy d'API Kubernetes intégré
Pourquoi Talos nécessite une configuration Cilium spéciale¶
Talos ne permet pas les installations CNI traditionnelles. Vous devez configurer Cilium pour fonctionner avec les contraintes de Talos :
| Exigence | Valeur Talos | Pourquoi |
|---|---|---|
| Nom CNI | none | Talos ne gère pas le CNI |
| Kube-proxy | disabled | Cilium remplace kube-proxy avec eBPF |
| Montage CGroup | /sys/fs/cgroup | Pré-monté par Talos |
| AutoMount CGroup | false | Talos fournit déjà cgroup v2 |
| Capacités | Ensemble restreint | Pas de SYS_MODULE (modules kernel interdits) |
| Serveur API K8s | localhost:7445 | Proxy local KubePrism |
KubePrism
KubePrism est un proxy de serveur API Kubernetes local qui s'exécute sur chaque nœud Talos sur localhost:7445. Cela fournit un accès API hautement disponible sans load balancers externes, ce qui est critique lors de l'exécution de Cilium avec kubeProxyReplacement=true.
Flux réseau avec les annonces L2¶
Voici comment le trafic circule lors de l'accès à un service LoadBalancer en externe (hors du cluster) :
sequenceDiagram
participant Client as PC/Appareil Externe
participant Network as Réseau Local
participant LeaderNode as Nœud Kubernetes<br/>(Leader L2)
participant Cilium as Agent Cilium
participant Pod as Pod Backend
Note over Client,Pod: 1. Phase de découverte ARP
Client->>Network: ARP: Qui a 192.168.10.75?
Network->>LeaderNode: Diffusion vers tous les nœuds
Cilium->>Network: Réponse ARP: Je l'ai! (MAC: XX:XX:XX:XX:XX:XX)
Note over Client,Pod: 2. Phase de transfert du trafic
Client->>LeaderNode: HTTP GET / (vers 192.168.10.75)
LeaderNode->>Cilium: Le paquet arrive sur NIC
Cilium->>Pod: eBPF redirige vers le pod backend
Pod->>Cilium: Réponse HTTP
Cilium->>LeaderNode: eBPF traite le trafic de retour
LeaderNode->>Client: Réponse HTTP transmise Points clés :
- Élection du leader - Un nœud par IP LoadBalancer devient le "leader" via des baux Kubernetes
- Répondeur ARP - Le nœud leader répond aux requêtes ARP pour l'IP LoadBalancer
- Magie eBPF - Cilium utilise des programmes eBPF pour transférer efficacement le trafic vers les pods
Installation étape par étape¶
Étape 1 : Préparer la configuration machine Talos¶
Tout d'abord, configurez Talos pour désactiver le CNI par défaut et kube-proxy. Créez un fichier de patch pour votre configuration Talos :
| talos-cilium-patch.yaml | |
|---|---|
- Indiquez à Talos de ne pas installer de CNI - nous installerons Cilium manuellement
- Désactivez kube-proxy puisque Cilium le remplacera avec eBPF.
Appliquez ce patch lors de la génération ou de la mise à jour de votre configuration Talos :
# Si vous générez une nouvelle config de cluster
talosctl gen config \
my-cluster https://mycluster.local:6443 \
--config-patch @talos-cilium-patch.yaml
# Si vous mettez à jour un cluster existant
talosctl patch machineconfig \
--nodes <node-ip> \
--patch @talos-cilium-patch.yaml
Redémarrage du nœud requis
Après avoir appliqué ce patch, les nœuds redémarreront. Pendant le processus de démarrage, les nœuds sembleront bloqués à "phase 18/19" en attendant le CNI. C'est normal—les nœuds ne deviendront pas Ready tant que Cilium n'est pas installé.
Étape 2 : Installer Cilium avec support L2¶
Maintenant, nous allons installer Cilium en utilisant Helm avec les annonces L2 activées.
Créez un fichier de valeurs Helm complet :
- Utiliser l'IPAM natif de Kubernetes pour l'allocation des IP de pods
- Remplacer kube-proxy par l'implémentation eBPF de Cilium
- Capacités Linux requises pour l'agent Cilium (notez :
SYS_MODULEn'est pas inclus pour Talos) - Capacités pour le processus de nettoyage Cilium
- Critique pour Talos - Ne pas monter automatiquement cgroup, Talos le fournit
- Critique pour Talos - Chemin vers le cgroup v2 pré-monté de Talos
- Critique pour Talos - Utiliser le proxy local KubePrism
- Critique pour Talos - Port KubePrism (par défaut : 7445)
- Activer le support Gateway API (utile pour le routage avancé)
- Activer les annonces L2 - Cela rend les IP LoadBalancer accessibles en externe
- Durée du bail d'élection du leader pour les annonces L2
- Activer la découverte de voisins - Requis pour les réponses ARP
Installez Cilium en utilisant Helm :
# Ajouter le dépôt Helm Cilium
helm repo add cilium https://helm.cilium.io/
helm repo update
# Vérifier les versions plus récentes sur https://artifacthub.io/packages/helm/cilium/cilium
# Installer Cilium avec support L2
helm install cilium cilium/cilium \
--version 1.18.0 \
--namespace kube-system \
--values cilium-values.yaml \
--wait \
--timeout 10m
Après l'installation, vérifiez que Cilium fonctionne :
# Vérifier les pods Cilium
kubectl get pods -n kube-system -l k8s-app=cilium
# Sortie attendue :
NAME READY STATUS RESTARTS AGE
cilium-4cpgk 1/1 Running 0 2m
cilium-99sz2 1/1 Running 0 2m
cilium-tqpvv 1/1 Running 0 2m
Vos nœuds Talos devraient maintenant devenir Ready :
kubectl get nodes
NAME STATUS ROLES AGE VERSION
cp1-lab.home.mombesoft.com Ready control-plane 10m v1.33.1
node1-lab.home.mombesoft.com Ready <none> 10m v1.33.1
Cilium installé !
À ce stade, le CNI Cilium est complètement opérationnel. Cependant, les services LoadBalancer ne fonctionneront toujours pas tant que nous n'aurons pas configuré les annonces L2 dans les prochaines étapes.
Étape 3 : Appliquer les permissions RBAC pour les annonces L2¶
Cilium a besoin de permissions pour gérer les baux Kubernetes pour l'élection du leader L2. Créez les ressources RBAC :
- Le groupe API
coordination.k8s.iogère les primitives de coordination distribuée comme les baux - Les baux sont utilisés pour l'élection du leader - un nœud devient le "leader" pour chaque IP LoadBalancer
- Lier les permissions au compte de service Cilium
Appliquez la configuration RBAC :
Vérifiez les permissions :
# Tester si Cilium peut gérer les baux
kubectl auth can-i get leases \
--as=system:serviceaccount:kube-system:cilium \
-n kube-system
# Devrait afficher : yes
Étape critique
Sans ces permissions RBAC, Cilium journalisera des erreurs comme :
Et les annonces L2 ne fonctionneront pas.Étape 4 : Créer le pool d'IP LoadBalancer¶
Définissez maintenant la plage d'adresses IP que Cilium peut attribuer aux services LoadBalancer. Choisissez des IP de votre réseau local qui sont :
- ✅ Dans le même sous-réseau que vos nœuds Kubernetes
- ✅ Non utilisées par votre serveur DHCP
- ✅ Non attribuées à d'autres appareils
| cilium-loadbalancer-ippool.yaml | |
|---|---|
- Nommez votre pool d'IP (vous pouvez avoir plusieurs pools pour différents usages)
- Première adresse IP dans le pool (inclusive)
- Dernière adresse IP dans le pool (inclusive) - Cela vous donne 4 IP au total
Choix des adresses IP
Exemple de réseau: 192.168.10.0/24
- Routeur:
192.168.10.1 - Plage DHCP:
192.168.10.100-192.168.10.200 - Nœuds Kubernetes:
192.168.10.215-192.168.10.220 - Pool LoadBalancer:
192.168.10.75-192.168.10.78✅ Choix sûr
Assurez-vous que ces IP sont en dehors de votre plage DHCP et non déjà attribuées.
Appliquez le pool d'IP :
Vérifiez le pool d'IP :
kubectl get ciliumloadbalancerippool
# Sortie attendue :
NAME DISABLED CONFLICTING IPS AVAILABLE AGE
lab-lb-pool false False 4 10s
Étape 5 : Créer la politique d'annonce L2¶
La politique d'annonce L2 indique à Cilium quelle interface réseau utiliser pour annoncer les IP LoadBalancer via ARP (Address Resolution Protocol). Ceci est nécessaire car les services LoadBalancer Kubernetes s'appuient sur ARP.
Identifiez d'abord votre interface réseau sur les nœuds Talos :
# Obtenir le nom de l'interface depuis un nœud Talos
talosctl get links -n <node-ip>
# Exemple de sortie :
NODE NAMESPACE TYPE ID VERSION HARDWARE ADDR MTU
192.168.10.216 network LinkStatus enp0s1 2 f2:83:d9:c5:82:97 1500
192.168.10.216 network LinkStatus eth0 1 aa:bb:cc:dd:ee:ff 1500
Noms d'interface courants sur Talos :
enp0s1- Périphérique réseau PCIe (courant dans les VM)eth0- Périphérique Ethernetens18- Autre convention de nommage PCIe
Maintenant, créez la politique d'annonce L2 :
| cilium-l2-announcement-policy.yaml | |
|---|---|
- Nommez votre politique L2 (vous pouvez avoir plusieurs politiques)
- Annoncer les IP des services LoadBalancer (ce que nous voulons !)
- Annoncer également les IP externes si les services utilisent le champ
externalIPs - Critique : Remplacez par le nom réel de votre interface de l'étape 5
- Sélecteur vide = s'applique à tous les nœuds (recommandé pour la plupart des configurations)
- Sélecteur vide = annoncer tous les services (recommandé pour la plupart des configurations)
Appliquez la politique L2 :
Vérifiez la politique :
Le nom de l'interface est critique
Si vous spécifiez le mauvais nom d'interface, les annonces ARP ne fonctionneront pas et les IP LoadBalancer seront inaccessibles. Vérifiez bien avec talosctl get links -n <node-ip>.
Étape 6 : Déployer un service LoadBalancer de test¶
Testons maintenant la configuration complète en déployant nginx avec un service LoadBalancer :
# Créer un namespace de test
kubectl create namespace test-loadbalancer
# Déployer nginx
kubectl create deployment nginx \
--image=nginx:latest \
--namespace=test-loadbalancer
# Exposer nginx en tant que service LoadBalancer
kubectl expose deployment nginx \
--type=LoadBalancer \
--port=80 \
--namespace=test-loadbalancer
Surveillez le service obtenir une IP externe :
kubectl get svc nginx -n test-loadbalancer --watch
# Progression attendue :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
nginx LoadBalancer 10.43.100.50 <pending> 80:30492/TCP
nginx LoadBalancer 10.43.100.50 192.168.10.75 80:30492/TCP ✅
IP externe attribuée !
Si vous voyez une IP de votre pool (par exemple, 192.168.10.75), félicitations ! Le LB-IPAM de Cilium fonctionne.
Étape 7 : Vérifier l'accès externe¶
Testez maintenant que l'IP LoadBalancer est réellement accessible de l'extérieur du cluster :
Depuis votre machine locale¶
# Tester l'accès HTTP
curl http://192.168.10.75
# Sortie attendue :
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Vérifier la table ARP¶
Vérifiez que votre machine a appris l'adresse MAC pour l'IP LoadBalancer :
# Sur macOS/Linux
arp -a | grep 192.168.10.75
# Sortie attendue (adresse MAC présente) :
? (192.168.10.75) at c2:d2:76:e3:7:ab on en1 ifscope [ethernet]
# Mauvaise sortie (signifie que les annonces L2 ne fonctionnent pas) :
? (192.168.10.75) at (incomplete) on en1 ifscope [ethernet] ❌
Signification de l'entrée ARP
- Adresse MAC présente (par exemple,
c2:d2:76:e3:7:ab) = Les annonces L2 fonctionnent ✅ (incomplete)= Le nœud ne répond pas aux requêtes ARP ❌
Étape 8 : Vérifier les annonces L2¶
Vérifions en profondeur que Cilium annonce correctement l'IP LoadBalancer :
Vérifier la configuration Cilium¶
# Obtenir un nom de pod Cilium
CILIUM_POD=$(kubectl get pod -n kube-system -l k8s-app=cilium -o jsonpath='{.items[0].metadata.name}')
# Vérifier que les annonces L2 sont activées
kubectl exec -n kube-system $CILIUM_POD -- cilium-dbg debuginfo | grep enable-l2
# Sortie attendue :
enable-l2-announcements:true ✅
enable-l2-neigh-discovery:true ✅
enable-l2-pod-announcements:false ℹ️ (pas nécessaire pour LoadBalancer)
Vérifier les baux d'élection du leader¶
Pour chaque service LoadBalancer, Cilium crée un bail pour l'élection du leader :
# Lister les baux d'annonce L2
kubectl get leases -n kube-system | grep l2announce
# Sortie attendue :
NAME HOLDER AGE
cilium-l2announce-test-loadbalancer-nginx cp1-lab.home.mombesoft.com 2m
La colonne HOLDER montre quel nœud est actuellement le leader pour annoncer cette IP LoadBalancer.
Vérifier le mappage de service Cilium¶
# Vérifier si Cilium connaît le service LoadBalancer
kubectl exec -n kube-system $CILIUM_POD -- cilium-dbg service list | grep 192.168.10.75
# Sortie attendue :
20 192.168.10.75:80/TCP LoadBalancer
24 192.168.10.75:80/TCP/i LoadBalancer 1 => 10.244.2.98:80/TCP (active)
Vérifier les tables BPF LoadBalancer¶
# Vérifier les mappages eBPF du load balancer
kubectl exec -n kube-system $CILIUM_POD -- cilium-dbg bpf lb list | grep 192.168.10.75
# Sortie attendue :
192.168.10.75:80/TCP (1) 10.244.2.98:80/TCP (20) (1)
192.168.10.75:80/TCP/i (0) 0.0.0.0:0 (24) (0) [LoadBalancer, Cluster, two-scopes]
Toutes les vérifications réussies !
Si toutes les étapes de vérification montrent des résultats positifs, votre configuration Cilium L2 LoadBalancer est entièrement opérationnelle !
Comprendre les politiques de trafic¶
Les services LoadBalancer Kubernetes supportent deux politiques de trafic via le champ externalTrafficPolicy :
Cluster (Par défaut)¶
Comportement :
- N'importe quel nœud du cluster peut recevoir du trafic externe
- Le trafic est transmis aux pods sur n'importe quel nœud (même s'il n'est pas local)
- L'IP source est SNAT'd (l'IP du client est perdue)
Avantages :
- ✅ Fonctionne quel que soit le nœud qui est le leader L2
- ✅ Distribution de charge égale entre les pods
- ✅ Configuration plus simple
Inconvénients :
- ❌ L'IP source du client n'est pas préservée
- ❌ Saut réseau supplémentaire si le pod est sur un nœud différent
Local¶
Comportement :
- Seuls les nœuds avec des pods locaux répondent au trafic
- Pas de SNAT - l'IP source du client est préservée
- Routage direct vers le pod local
Avantages :
- ✅ L'IP source du client est préservée (important pour les logs, la sécurité)
- ✅ Pas de saut réseau supplémentaire
- ✅ Latence plus faible
Inconvénients :
- ❌ La charge peut être inégale si les pods ne sont pas distribués uniformément
- ❌ Le leader d'annonce L2 doit avoir un pod local
- ❌ Configuration plus complexe
Piège de la politique Local
Avec externalTrafficPolicy: Local, si le nœud annonçant l'IP LoadBalancer (leader L2) n'a pas de réplique de pod, le trafic échouera. Pour la plupart des utilisateurs, Cluster est le choix le plus sûr.
Points clés à retenir¶
Ce que nous avons accompli
✅ Installé Cilium sur Talos avec configuration appropriée de KubePrism et cgroup
✅ Activé les annonces L2 pour l'accessibilité des IP LoadBalancer
✅ Configuré les permissions RBAC pour l'élection du leader Cilium
✅ Créé un pool d'IP pour l'allocation des IP LoadBalancer
✅ Défini la politique L2 spécifiant l'interface réseau pour ARP
✅ Déployé et vérifié un service LoadBalancer fonctionnel
✅ Compris les politiques de trafic et leurs implications
Prochaines étapes¶
Maintenant que vous avez une configuration LoadBalancer fonctionnelle, explorez :
- Configurer des politiques L2 avancées - Sélecteurs de nœuds, sélecteurs de services, pools d'IP multiples
- Dépanner les problèmes LoadBalancer - Problèmes courants et solutions
- Comprendre l'architecture réseau L2 - Plongée approfondie dans le fonctionnement
- Déployer de vrais services - Appliquer le type LoadBalancer à vos charges de travail réelles
Nettoyage (Optionnel)¶
Pour supprimer le service LoadBalancer de test :
Références¶
- Talos Linux - Deploying Cilium CNI
- Documentation Cilium - LB-IPAM
- Documentation Cilium - Annonces L2
- Kubernetes - Service External Traffic Policy
Tutoriel terminé ! Vous avez maintenant une solution LoadBalancer prête pour la production sur votre cluster Talos Linux bare-metal.