eBPF : Comment Linux est devenu un noyau sûr, rapide et programmable

Le problème avec l'ancienne approche
Pendant des décennies, si vous vouliez modifier la façon dont le noyau Linux traitait les paquets, filtrait les appels système ou traquait les goulots d'étranglement de performance, vous n'aviez que deux options : soumettre un patch noyau et attendre des années qu'il soit intégré dans les distributions, ou écrire un module noyau. Les modules noyau sont puissants mais dangereux. Un bug dans un module fait planter l'hôte. Ils sont spécifiques à une version du noyau, si bien qu'un module compilé pour la 5.15 casse sur la 6.1. Les déployer sur un parc hétérogène implique de maintenir des dizaines de builds. Pour une entreprise qui gère des centaines de milliers de serveurs, ce n'est pas un problème d'ingénierie — c'est une source de risques.
eBPF résout ce problème. Il vous permet d'injecter une logique personnalisée dans le noyau en cours d'exécution — pour le réseau, la sécurité ou l'observabilité — de manière sûre, portable, et sans redémarrer quoi que ce soit.
Ce qu'est réellement eBPF
BPF (Berkeley Packet Filter) a été créé en 1992 pour rendre tcpdump plus rapide. Au lieu de copier chaque paquet vers l'espace utilisateur pour le filtrer, BPF faisait tourner une petite machine virtuelle dans le noyau afin de filtrer les paquets sur place. Son périmètre était volontairement limité.
En 2014, Alexei Starovoitov et Daniel Borkmann ont introduit extended BPF dans Linux 3.18. Le jeu d'instructions a été repensé pour les architectures 64 bits, le nombre de registres étendu, et — point crucial — les points d'accroche disponibles ont explosé bien au-delà du simple filtrage de paquets. Aujourd'hui, vous pouvez attacher des programmes eBPF aux chemins réseau entrants et sortants, aux tracepoints, aux kprobes (sondes dynamiques de fonctions noyau), aux uprobes (sondes de fonctions en espace utilisateur) et aux points d'entrée/sortie des appels système. Le noyau est devenu programmable.
Le modèle de sécurité est ce qui rend eBPF utilisable en production. Vous écrivez un programme eBPF en C restreint, ou en utilisant des bibliothèques Go ou Rust qui émettent du bytecode eBPF. Avant l'exécution du programme, le vérificateur du noyau analyse statiquement chaque chemin d'exécution possible : pas de boucles non bornées, pas d'accès mémoire hors limites, pas d'arithmétique de pointeurs non sécurisée. Les programmes qui échouent à la vérification sont rejetés purement et simplement. Ceux qui la passent sont compilés en JIT en code machine natif — il n'y a donc aucune surcharge d'interpréteur à l'exécution. Le résultat : du code qui s'exécute dans le noyau à une vitesse quasi native, avec des garanties de sécurité appliquées automatiquement par le noyau.
XDP et la révolution réseau
La capacité eBPF la plus spectaculaire pour les équipes d'infrastructure est XDP — eXpress Data Path. Les hooks XDP s'exécutent avant même que la pile réseau du noyau ne traite un paquet. Avant l'allocation du sk_buff. Avant la consultation de la table de routage. Avant tout. Un programme XDP peut rejeter, rediriger ou modifier un paquet au niveau du pilote NIC à plus de 100 millions de paquets par seconde sur du matériel standard.
Pour la défense contre les DDoS, cela change tout. Une attaque volumétrique qui saturerait le chemin réseau normal du noyau — remplissant les files d'attente des sockets, épuisant le CPU sur la gestion des interruptions — est rejetée au niveau du pilote avant que tout cela ne se produise. Cloudflare utilise des programmes eBPF basés sur XDP pour absorber des attaques DDoS à l'échelle du térabit. Le paquet n'atteint jamais la pile. L'hôte reste opérationnel.
Meta est allé encore plus loin. Ils ont remplacé toute leur infrastructure d'équilibrage de charge — précédemment construite sur IPVS — par Katran, un load balancer eBPF/XDP open-source. Katran tourne sur chaque serveur des datacenters de Meta, gérant un trafic à l'échelle de Facebook sans appliances dédiées. La flexibilité d'eBPF signifie qu'ils peuvent mettre à jour la logique d'équilibrage de charge en chargeant un nouveau programme, sans redémarrage ni redéploiement matériel.
Le réseau Kubernetes via Cilium
La problématique réseau de Kubernetes est complexe. Chaque pod a besoin d'une IP. Les pods doivent communiquer entre les nœuds. Les politiques réseau doivent être appliquées. L'équilibrage de charge des services doit fonctionner. La réponse traditionnelle était iptables — un moteur de règles qui ne passe pas à l'échelle. À quelques milliers de règles, la consultation iptables devient O(n) et la consommation CPU augmente de façon visible. À des dizaines de milliers de pods, le système s'effondre.
Cilium remplace entièrement iptables par eBPF. Le routage pod à pod, l'équilibrage de charge des services et l'application des politiques réseau se font tous dans des programmes eBPF attachés aux interfaces réseau. Les consultations sont en O(1) grâce aux hash maps eBPF. L'application des politiques se produit dans le chemin rapide du noyau. Cilium comprend également HTTP, gRPC et Kafka en couche 7 — car les programmes eBPF peuvent inspecter les charges utiles des paquets, pas seulement leurs en-têtes.
L'adoption est éloquente. AWS EKS, Google GKE et Azure AKS proposent tous Cilium comme CNI par défaut ou recommandé. Des clusters Kubernetes de plusieurs centaines de nœuds et de milliers de pods utilisent eBPF pour chaque décision de paquet, et le goulot d'étranglement iptables a disparu.
Observabilité sans instrumentation
Les outils APM traditionnels exigent des modifications du code : ajouter une bibliothèque, envelopper des fonctions, redéployer. L'observabilité eBPF n'exige rien de tout cela. Vous attachez un kprobe ou un uprobe à n'importe quelle fonction noyau ou en espace utilisateur et collectez des données — latence, arguments, valeurs de retour, traces de pile — sans modifier l'application.
Netflix utilise bpftrace en production à cet effet précis. bpftrace est un langage de script de haut niveau pour eBPF, comparable à ce qu'était DTrace sur Solaris. Une simple commande peut tracer chaque I/O disque dépassant 1ms sur un hôte de production, ou produire un histogramme des latences de connexion TCP, ou identifier quels processus provoquent le plus de changements de contexte — le tout avec une surcharge mesurée en quelques points de pourcentage, et non les 10 à 30 % d'un profilage traditionnel.
Pixie va encore plus loin pour Kubernetes, en instrumentant automatiquement chaque service d'un cluster via eBPF pour capturer les données requête/réponse, les distributions de latence et les taux d'erreur, sans aucune configuration par service. Pas de sidecars. Pas d'intégration SDK. L'observabilité est intégrée dans la couche noyau.
Application de la sécurité au niveau du noyau
seccomp-BPF filtre les appels système dans les conteneurs Linux depuis des années — c'est ce que Docker, Chrome et Firefox utilisent pour restreindre les appels système qu'un processus sandboxé peut effectuer. C'est l'usage le plus limité d'eBPF en matière de sécurité.
L'usage le plus étendu concerne l'application de la sécurité à l'exécution. Falco utilise eBPF pour surveiller chaque appel système dans un cluster Kubernetes et alerter sur les comportements suspects — un conteneur qui lance un shell, un processus qui écrit dans /etc, une connexion réseau vers une IP inattendue. Tetragon, issu du projet Cilium, va plus loin : il peut non seulement détecter les violations de politique en temps réel, mais aussi les appliquer en tuant le processus fautif avant que l'appel système ne se termine. La logique de politique s'exécute dans le noyau via eBPF. Il n'existe aucune fenêtre de course entre la détection et la réponse.
Portabilité : CO-RE et BTF
Un reproche persistant à l'égard d'eBPF concernait le verrouillage sur une version du noyau. Un programme eBPF compilé avec les en-têtes du noyau 5.15 pouvait ne pas fonctionner sur la 6.1 si les layouts de structures avaient changé. CO-RE — Compile Once, Run Everywhere — résout ce problème. Avec BTF (BPF Type Format), le noyau expose ses informations de types internes à l'exécution. Le chargeur eBPF utilise BTF pour relocaliser les accès aux champs au moment du chargement, adaptant le programme compilé au noyau effectivement en cours d'exécution. Un seul binaire eBPF peut désormais s'exécuter sur tout un parc de noyaux hétérogènes sans recompilation.
Ce qui vient ensuite
Microsoft travaille activement au portage d'eBPF sur Windows via le projet ebpf-for-windows. Les fabricants de SmartNIC ajoutent le support matériel pour les programmes eBPF, de sorte que le filtrage XDP peut s'exécuter directement sur la carte réseau, libérant entièrement les CPU hôtes. Les environnements d'exécution eBPF en espace utilisateur arrivent à maturité, permettant une extensibilité sandboxée de type eBPF en dehors du noyau.
Le schéma sous-jacent est constant : un mécanisme d'extension programmable avec de solides garanties de sécurité surpasse le code noyau statique pour tout ce qui doit évoluer à la vitesse de la production. eBPF n'a pas seulement amélioré le réseau et l'observabilité sous Linux — il a changé le modèle même d'extension du comportement du noyau. Les équipes infrastructure qui l'ont compris tôt avancent plus vite, de manière plus sûre et à plus grande échelle que celles qui écrivent encore des règles iptables et des modules noyau.