eBPF est une technologie de programmation événementielle qui permet aux développeurs d’écrire des programmes efficaces, sûrs et non intrusifs qui s’exécutent directement dans l’espace du noyau du système d’exploitation (OS) de Linux, « étendant » effectivement le noyau du système d’exploitation.
Le noyau d’un système d’exploitation est une entité extrêmement stable, et intentionnellement. De par sa conception, il prend en charge l’ensemble du système d’exploitation. Il peut être compliqué et fastidieux de l’amender ou de le modifier. Les eBPF répondent à ce défi d’extensibilité en permettant aux développeurs d’exécuter des programmes en mode sandbox dans des contextes privilégiés, tels que le noyau d’un système d’exploitation.
La pile du système d’exploitation peut être décomposée en trois couches logiques : la couche matérielle, la couche noyau et la couche utilisateur. La couche noyau est le cœur d’un système d’exploitation. Il se situe entre la couche physique, qui héberge tout le matériel physique, la mémoire et les composants de stockage d’un système d’exploitation, et la couche utilisateur, qui héberge les navigateurs Web et les applications d’un système d’exploitation.
Les applications et navigateurs dans l’espace utilisateur doivent communiquer avec les composants de la couche physique pour accomplir leurs tâches respectives, mais chaque composant de la couche physique a des protocoles de communication spécifiques et des exigences de compatibilité. C’est là que la couche noyau (ou l’espace du noyau) entre en jeu. Il interprète les appels système et permet aux applications de communiquer efficacement avec les composants du réseau physique.
Les outils eBPF aident les développeurs à étendre plus facilement les fonctionnalités des logiciels existants au moment de l’exécution, sans modifier le code source du noyau, sans charger les modules du noyau (éléments de code chargeables qui peuvent étendre les fonctions du noyau) ni sans perturber l’espace du noyau.
Les technologies eBPF représentent une évolution du filtre de paquets Berkeley (BPF) original, qui offrait un moyen simple de sélectionner et d’analyser les paquets du réseau dans un programme de l’espace utilisateur. Mais au-delà du filtrage des paquets, les programmes BPF n’avaient pas la flexibilité nécessaire pour gérer des tâches plus complexes au sein du noyau.
Constatant le besoin d’une technologie plus polyvalente, la communauté Linux a développé l’eBPF à partir des fonctionnalités backend du BPF mais en étendant sa programmabilité dans le noyau. Les fonctionnalités avancées des programmes eBPF et leur approche de bac à sable permettent aux développeurs d’implémenter des processus de filtrage de paquets améliorés, d’améliorer les capacités d’observabilité et de surveillance de l’espace noyau, d’effectuer des analyses de performance haut de gamme et d’appliquer des politiques de sécurité au niveau du noyau dans les centres de données sur site et les environnements cloud natifs.
Les principaux composants d’un programme eBPF sont :
Les programmes eBPF sont initialement écrits dans un sous-ensemble C restreint, puis compilés dans le bytecode eBPF à l’aide d’outils comme LLVM, qui sert d’architecture backend à l’eBPF pour les langages de programmation frontend comme Clang. Le bytecode est essentiellement un ensemble restreint d’instructions qui respectent l’architecture du jeu d’instructions eBPF et empêchent les erreurs d’exécution.
La technologie de noyau Linux peut convertir le bytecode eBPF en actions exécutables, mais les compilateurs juste-à-temps (JIT) offrent des performances supérieures. Les compilateurs JIT peuvent convertir le bytecode en code machine natif pour des plateformes matérielles spécifiques selon les besoins.
Les chargeurs d’espace utilisateur sont des programmes dans l’espace utilisateur qui chargent le bytecode eBPF dans le noyau, le fixent aux hooks appropriés et gèrent toutes les cartes eBPF associées. Parmi les exemples de chargeurs d’espace utilisateur, citons des outils tels que BPF Compiler Collection (BCC) et bpftrace.
Les cartes eBPF sont des structures de données comportant des paires clé-valeur et un accès en lecture et en écriture qui fournissent un espace de stockage partagé et facilitent l’interaction entre les programmes de noyau eBPF et les applications d’espace utilisateur. Créées et gérées par des appels système, les cartes eBPF peuvent également être utilisées pour maintenir l'état entre différentes itérations des programmes eBPF.
Le vérificateur, un composant essentiel des systèmes eBPF, vérifie le bytecode avant qu’il ne soit chargé dans le noyau pour s’assurer que le programme ne contient aucune opération nuisible, comme des boucles infinies, des instructions illégales ou l’accès mémoire hors limites. Celui-ci aide également à s'assurer que tous les chemins de données du programme se terminent correctement.
Les hooks sont des points d’ancrage dans le code du noyau où les programmes eBPF peuvent être attachés. Lorsque le noyau atteint un hook, il exécute le programme eBPF attaché.
Différents types de hooks tels que les points de trace, les kprobes, les uprobes et les files d’attente de réception de paquets réseau procurent aux programmes eBPF un large accès aux données et leur permettent d’effectuer diverses opérations. Les points de trace, par exemple, permettent aux programmes d’inspecter et de collecter des données sur le noyau ou d’autres processus, tandis que les hooks de contrôle du trafic peuvent être utilisés pour inspecter et modifier les paquets réseau. Et kprobes et uprobes facilitent le traçage dynamique au niveau du noyau et au niveau de l'utilisateur.
Les XDP sont des chemins de données haute performance qui accélèrent le traitement des paquets au niveau du pilote et facilitent le transfert entre les couches de communication. Ils permettent aux systèmes eBPF de prendre des décisions de routage des données avant même que les paquets de données n’atteignent le noyau.
L’intégration des XDP au noyau Linux (au milieu des années 2010) a finalement permis aux développeurs de déployer des fonctions d’équilibrage de charge basées sur l’eBPF, capables de gérer le trafic de données dans les centres de données les plus actifs.
Comme les eBPF ne peuvent pas générer de fonctions arbitraires et doivent maintenir la compatibilité avec chaque version possible du noyau, parfois les jeux d'instructions eBPF de base ne sont pas assez nuancés pour exécuter des opérations avancées. Les fonctions d’assistance permettent d’y remédier.
Les fonctions d’assistance (ensembles de fonctions de noyau prédéfinies basées sur des APIque les eBPF peuvent appeler depuis le système) permettent aux programmes eBPF d’effectuer des opérations plus complexes (comme obtenir l’heure et la date actuelles ou générer des nombres aléatoires) qui ne sont pas directement prises en charge par le jeu d’instructions.
En général, les eBPF fonctionnent comme des machines virtuelles (VM) à l’intérieur du noyau Linux, opérant sur une architecture de jeu d’instructions de bas niveau et exécutant le bytecode eBPF. Cependant, le processus complexe d’exécution d’un programme eBPF suit généralement certaines étapes principales.
Les développeurs écrivent d’abord le programme eBPF et compilent le bytecode. L’objectif du programme détermine le type de code approprié. Par exemple, si une équipe souhaite surveiller l’utilisation du processeur, elle écrit du code qui inclut la fonctionnalité permettant de capturer les métriques d’utilisation.
Une fois le code C de haut niveau converti en bytecode de niveau inférieur par le compilateur eBPF, un chargeur d’espace utilisateur génère un appel système BPF pour charger le programme dans le noyau. Le chargeur assure également la résolution des erreurs et la configuration des cartes eBPF dont le programme a besoin.
Avec le bytecode du programme et les cartes en place, l’eBPF exécutera un processus de vérification pour confirmer que le programme est sûr à exécuter dans le noyau. S’il est considéré comme dangereux, l’appel système pour charger le programme échoue et le programme du chargeur reçoit un message d’erreur. Si le programme passe la vérification, l’exécution est autorisée.
À l’aide d’un interprète ou d’un compilateur JIT, l’eBPF convertira le bytecode en code machine exploitable. Cependant, eBPF est une technologie basée sur les événements, elle s’exécute donc en réponse à des points de hook ou des événements spécifiques dans le noyau (appels système, événements réseau, initiation de processus, inactivité du CPU, par exemple). Lorsqu’un événement se produit, l’eBPF exécute le programme bytecode correspondant, permettant aux développeurs d’inspecter et de manipuler divers composants du système.
Lorsque le programme eBPF est en cours d’exécution, les développeurs peuvent interagir avec lui depuis l’espace utilisateur à l’aide de cartes eBPF. Par exemple, l’application peut vérifier périodiquement une carte pour collecter des données à partir du programme eBPF, ou mettre à jour une carte pour modifier le comportement du programme.
Le déchargement du programme est la dernière étape de la plupart des processus d’exécution eBPF. Lorsque l’eBPF a terminé sa tâche, le chargeur peut utiliser à nouveau l’appel système BPF pour le décharger du noyau ; l’eBPF cesse alors de fonctionner et libère ses ressources associées. Le processus de déchargement peut également inclure une itération sur toutes les cartes eBPF dont l’équipe n’a plus besoin pour libérer des éléments individuels utiles, puis la suppression de la carte elle-même (à l’aide de l’appel système « supprimer »).
Le Berkeley Packet Filter (BPF) a été initialement développé comme un mécanisme de filtrage des paquets dans les systèmes basés sur Unix, permettant au code au niveau utilisateur de définir des filtres capables de capturer et traiter efficacement les paquets réseau au sein du noyau. Ainsi, cette approche minimisait la puissance nécessaire pour transférer des données inutiles vers l’espace utilisateur et pouvait rationaliser et optimiser les réseaux informatiques.
BPF utilise un agent du noyau pour traiter les paquets au point d’entrée de la pile réseau. Une fois qu’un programme BPF est développé, il est chargé dans l’espace du noyau par un agent du noyau BPF, qui vérifie son exactitude avant de le connecter au socket concerné. Par conséquent, dans l’espace utilisateur, seuls les paquets correspondant au filtre du programme BPF peuvent recevoir des données d’un socket donné. Cette fonctionnalité de sauvegarde limite l’accès d’un programme aux zones de mémoire autorisées et prévient d’éventuelles pannes du noyau.
L'eBPF est apparu pour la première fois en 2014, date à laquelle il a représenté une évolution significative par rapport au concept initial du BPF. En plus des cas d’utilisation réseau originaux, les applications eBPF se sont élargies pour inclure des appels système et d’autres fonctions, c’est pourquoi les développeurs l’appelaient souvent le « Extended Berkeley Packet Filter ».
L’un des domaines clés où eBPF excelle est la surveillance des performances réseau. Il permet aux équipes informatiques d’effectuer des analyses et des dépannages en temps réel en fournissant des informations détaillées sur le comportement du réseau, les indicateurs de performance et les goulots d’étranglement. eBPF joue un rôle clé dans la sécurité du réseau, en surveillant et en filtrant les appels système et les activités réseau, en appliquant les politiques de sécurité du réseau et en détectant les anomalies du système.
eBPF offre également aux développeurs un outil précieux pour tracer et profiler à la fois les applications du noyau et de l’espace utilisateur, ainsi que pour exécuter des actions personnalisées et des transformations des données au fil du noyau, renforçant ainsi sa polyvalence et sa fonctionnalité. Grâce à ces capacités étendues (qui vont bien au-delà du filtrage de paquets), eBPF est désormais reconnu comme un terme à part entière, et non plus comme un acronyme pour Extended Berkeley Packet Filter.
Les progrès de la technologie eBPF ont permis aux développeurs de développer leurs applications sur tous les systèmes d’exploitation, afin que les plateformes non Linux puissent tirer parti des fonctionnalités sophistiquées de traçage, de mise en réseau et de surveillance de l’eBPF.1
En fait, la Fondation eBPF - une extension de la Fondation Linux dont les membres comprennent Google, Meta, Netflix, Microsoft, Intel et Isovalent, entre autres - a beaucoup investi dans l’expansion de la compatibilité des systèmes d’exploitation avec les programmes eBPF, dans l’espoir d’élargir à terme l’utilité de la programmation eBPF.2
Si le BPF a jeté les bases d’un filtrage efficace des paquets, l’eBPF a indéniablement élargi son champ d’application. Les eBPF modernes offrent un outil complet pour optimiser l’observabilité, la performance et la sécurité dans les systèmes Linux. Sa capacité à exécuter des programmes dynamiques définis par l’utilisateur au sein du noyau crée de nouvelles possibilités pour la surveillance et la gestion des systèmes, faisant de l’eBPF un outil indispensable tant pour les développeurs logiciels que pour les programmeurs informatiques.
Les technologies eBPF constituent déjà une pierre maîtresse des systèmes Linux modernes, car elles permettent un contrôle précis du noyau et aident les entreprises à concevoir des programmes plus innovants au sein de l’écosystème Linux.
L’eBPF a facilité les avancées dans les domaines suivants :
L’eBPF permet aux développeurs d’installer des fonctionnalités de traitement des paquets plus rapides et sur mesure, des processus d’équilibrage de charge, des scripts de profilage des applications et des pratiques de surveillance du réseau. Les plateformes open source, telles que Cilium, déploient l’eBPF pour fournir une mise en réseau sécurisée, évolutif et observable aux clusters Kubernetes et aux charges de travail, et à d’autres microservices conteneurisés.
L’eBPF aide également les équipes informatiques à imposer des règles simples et complexes dès le début du parcours de l’événement pour un routage du trafic, un filtrage du contenu et une prévention des pertes plus efficaces. En utilisant la logique de transfert de paquets au niveau du noyau, les eBPF peuvent minimiser la latence, rationaliser les processus de routage et permettre une réponse réseau globale plus rapide.
Lorsque les applications sont décomposées en microservices, l’observabilité dans l’espace utilisateur peut devenir difficile. Les eBPF offrent aux outils de surveillance une vue de l’espace du noyau afin que l’observabilité reste intacte de bout en bout.
Les eBPF permettent aux développeurs d’instrumenter les applications du noyau et de l’espace utilisateur pour collecter des données et des indicateurs de performance détaillés sans impact significatif sur les performances du système. Ces capacités aident les entreprises à garder une longueur d’avance, en permettant une surveillance et une observabilité en temps réel de chaque composant du réseau (et de ses dépendances).
Les eBPF peuvent surveiller les appels système, le trafic réseau et le comportement du système aux niveaux du noyau et des sockets pour détecter les menaces de sécurité potentielles et y répondre en temps réel. Falco (un outil de sécurité d’exécution cloud-natif), par exemple, utilise eBPF pour mettre en œuvre l’audit de sécurité en temps d’exécution et la réponse aux incidents, améliorant ainsi la sécurité globale du système.
De nombreux outils eBPF peuvent tracer les appels système, surveiller l’utilisation du processeur et suivre l’utilisation des ressources (E/S du disque, par exemple). Ces fonctionnalités aident les développeurs à détecter plus facilement les goulots d’étranglement dans les performances du système, à implémenter des protocoles de débogage et à identifier les possibilités d’optimisation.
Les eBPF peuvent installer et appliquer des politiques de sécurité au niveau du noyau (filtre de trafic réseau, pare-feu et restrictions de comportement, par exemple) et des contrôles de sécurité pour empêcher les acteurs malveillants et les utilisateurs non autorisés d’accéder au réseau.
Dans une architecture de microservices, la visibilité sur les charges de travail de production au sein du conteneur est essentielle. Cependant, les outils d’observabilité traditionnels peuvent peiner à suivre le rythme des microservices conteneurisés.
Par définition, les conteneurs sont éphémères. Ils sont créés en fonction de besoins et détruits dès qu’ils ont rempli leur objectif. Chaque conteneur agit comme un hôte individuel, et dans un environnement de production, le volume d’indicateurs qu’il crée peut facilement dépasser les outils de surveillance standard des applications, du réseau et de la surveillance de l’infrastructure. Les machines virtuelles peuvent se comporter de la même manière, mais la nature à cycle rapide des conteneurs peut compliquer la capture des données télémétriques.
De plus, les conteneurs sont souvent déployés en grand nombre dans des environnements cloud, ce qui rend la visibilité encore plus difficile.
L’eBPF, qui fonctionne au niveau du noyau d’un hôte ou d’un conteneur, permet aux développeurs de recueillir des données télémétriques à partir d’entités de données de courte durée. Elle permet d’intégrer la visibilité du réseau, des applications et de l’infrastructure dans un service unifié basé sur l’eBPF. Avec l’eBPF, les développeurs peuvent capturer des données sur les processus, l’utilisation de la mémoire, l’activité réseau et l’accès aux fichiers au niveau du conteneur, même si ceux-ci ne sont pas déployés dans le cloud.
De même, dans les environnements conteneurisés basés sur Kubernetes, l’eBPF utilise une interface unique et un ensemble d’outils pour collecter des données provenant de clusters disparates afin que les équipes informatiques n’aient pas à déployer des agents individuels de l’espace utilisateur pour effectuer des tâches de collecte de données à travers le réseau. Les outils eBPF peuvent fonctionner sur des nœuds de plan de contrôle (pour la surveillance des serveurs API, par exemple) et surveiller les nœuds worker pour générer des informations, en corrélant des points de données et des informations issus des deux types de nœuds pour une observabilité fine du cluster.
Red Hat OpenShift on IBM Cloud est une plateforme de conteneurs OpenShift entièrement gérée.
Virtualisation de stockage sécurisée, fiable et efficace pour les environnements VMware avec IBM Spectrum Virtualize.
Trouvez la solution d’infrastructure cloud adaptée aux besoins de votre entreprise et ajustez les ressources en fonction de la demande.
1 Foundation Proposes Advancing eBPF Adoption Across Multiple OSes, DevOps.com, 21 août 2021.
2 Latest eBPF Advances Are Harbingers of Major Changes to IT, DevOps.com, 13 septembre 2023.