Le noyau du système d’exploitation Linux est le programme principal qui s’exécute après le démarrage de l’ordinateur et permet au matériel et aux logiciels de « communiquer entre eux ». Comprendre cela permet de comprendre plus facilement pourquoi la technologie eBPF exploite le système d’exploitation pour mettre en œuvre l’observabilité, la sécurité et les performances du réseau, ce qui est essentiel à la connectivité exigée par la numérisation des entreprises d’aujourd’hui.
Défis de développement du noyau Linux
Linux s’est caractérisé par l’ouverture et la collaboration tout au long de son évolution depuis ses origines dans les années 90, ouvert aux modifications et aux redistributions au fil du temps. Ce modèle de licence open source a généré des contributions du monde entier, jetant les bases d’un développement collaboratif. Il est clair qu’il y avait initialement un certain scepticisme quant à la viabilité et au potentiel de Linux, car à cette époque, les systèmes propriétaires étaient préférés et l’idée d’un système d’exploitation libre et développé en collaboration soulevait des doutes. Cependant, l’ouverture et l’inclusion de Linux ont attiré les développeurs en raison de la possibilité d’utiliser, de modifier et de distribuer librement un système, une tendance qui se poursuit encore aujourd’hui.
Solution : Extended Berkeley Packet Filter (eBPF)
Les capacités du noyau ont continué à s’étendre, poussées par la collaboration et l’intelligence collective par les contributions des développeurs du monde entier. À cela s’est ajoutée l’adoption d’Internet : au début des années 90, Internet en était encore à ses débuts et les ingénieurs souhaitaient trouver des moyens de mieux comprendre le trafic circulant sur leurs réseaux. BPF a été conçu pour fournir un moyen de le faire sans avoir à modifier le code de tous les serveurs d’une organisation ou à dupliquer le code du noyau et à le mettre à jour avec des instructions d’instrumentation.
Qu’est-ce que l’eBPF ?
BPF signifiait à l’origine Berkeley Packet Filter et était utilisé pour enregistrer toutes les communications entrantes et sortantes TCP sur un serveur. Bien que cette approche nécessite moins de travail que la modification du code sur tous les serveurs, elle nécessitait tout de même des efforts importants pour créer le code et le déployer sur tous les serveurs de l’organisation, et elle ne pouvait accepter que les paquets avec un hachage signé dans l’en-tête. Lorsqu’un paquet entrant arrivait, le programme BPF était démarré et l’en-tête était vérifié pour voir si la valeur attendue était présente. En fonction des résultats, le paquet a été accepté ou rejeté. Cependant, il ne s’agissait plus seulement d’un filtrage, alors une version de BPF étendu ou eBPF est née.
Différences entre eBPF et GMP
Comme nous l’avons déjà mentionné, BPF est actuellement utilisé à diverses fins au-delà de la simple analyse et du filtrage du trafic réseau, en étendant ses fonctions et sa compatibilité avec 64 octets, ce qui permet une plus grande collecte et stockage d’informations. En effet, depuis la sortie du noyau 3.18, des filtres de paquets étendus Berkeley (eBPF) ont été créés pour enregistrer presque tous les événements du noyau. Les eBPF peuvent stocker et échanger plus de données et être utilisés à diverses fins, notamment la supervision, le suivi et l’optimisation des fonctions du noyau.
Dans le code source de Linux, on observe que le terme BPF persiste ; et dans les outils et la documentation, les termes BPF et eBPF sont généralement utilisés de manière interchangeable. Il a également été constaté que le BPF original est parfois appelé cBPF (BPF classique) pour le distinguer de l’eBPF.
Comment fonctionne l’eBPF
Pour comprendre comment l’eBPF est utilisé, il est important de comprendre les concepts clés :
- Hooks prédéfinis. Les programmes eBPF s’exécutent en fonction des événements qui les déclenchent : une application (ou le noyau) franchit un seuil appelé point de terminaison. Les hooks sont prédéfinis et incluent les événements réseau, les appels système ou sys, l’entrée et la sortie de fonction et les points de trace du noyau. S’il n’y a pas de liaison prédéfinie pour une exigence particulière, une sonde utilisateur ou un noyau (uprobe ou ksonde) peut être créé.
- Vérification du programme. Une fois qu’une liaison est identifiée, l’appel système BPF peut être utilisé pour charger le programme eBPF correspondant dans le noyau Linux. Cela implique l’utilisation d’une bibliothèque eBPF. Lorsqu’un programme est chargé dans le noyau, il est vérifié pour s’assurer qu’il peut être exécuté en toute sécurité, en tenant compte de conditions telles que :
- Le programme ne peut être chargé qu’à l’aide d’un processus eBPF privilégié (sauf indication contraire).
- Le programme n’endommagera pas ou ne plantera pas le système.
- Le programme fonctionnera toujours jusqu’à la fin (il ne restera pas dans une boucle sans fin).
- Cartes eBPF. Un programme eBPF doit être capable de stocker son état et de partager les données collectées. Les cartes eBPF peuvent aider les programmes à récupérer et à stocker des informations selon une variété de structures de données. Les utilisateurs peuvent accéder aux cartes eBPF via des appels système, à la fois à partir de programmes eBPF et d’applications. Les types de cartes sont les tables ou les tableaux de hachage, les tampons circulaires, le suivi de pile ou la correspondance de préfixes plus longues, entre autres.
- Appels d’aide (helper calls). Un programme eBPF ne peut pas appeler arbitrairement une fonction du noyau, car la compatibilité doit être maintenue ; donc les eBPF utilisent des fonctions d’assistance pour faire des appels de fonction. Les fonctions d’assistance sont des API (interfaces) fournies par le noyau et peuvent être facilement ajustées.
Les helper calls permettent aux programmes de générer des nombres aléatoires, de recevoir la date et l’heure actuelles, d’accéder aux cartes eBPF, de manipuler la logique de transfert et les paquets réseau, entre autres. - Appel de fonction (function call) et appel de queue (tail call) Ces appels signifient que les programmes eBPF peuvent être constitués de plusieurs éléments. Les appels de fonction vous permettent de définir et d’appeler des fonctions dans un programme. Les appels de file d’attente permettent à d’autres programmes eBPF de s’exécuter. Ils peuvent également modifier le contexte d’exécution.
Processus d’exécution du programme eBPF
eBPF permet aux développeurs d’écrire de petits programmes qui peuvent être attachés à différents points du noyau pour intercepter et traiter des données. Généralement écrits dans un sous-ensemble du langage de programmation C, les programmes sont ensuite compilés dans le bytecode eBPF, qui est ensuite chargé dans le noyau et exécuté. Contrairement aux modules de noyau traditionnels, les programmes eBPF sont faciles à déployer et à gérer, car ils ne nécessitent pas de modifications ou de compilation du code source du noyau.
Le programme eBPF suit une série d’étapes lorsqu’il s’exécute dans le noyau Linux :
- Une fois le programme eBPF écrit, il est compilé dans le bytecode eBPF. Le résultat est une représentation indépendante de la plate-forme du programme eBPF qui peut être exécutée dans le noyau.
- Ensuite, le bytecode eBPF est chargé dans le noyau. Le processus de chargement implique la vérification de la sécurité et de la compatibilité du bytecode avec le noyau en cours d’exécution, et l’allocation des ressources nécessaires à l’exécution du programme eBPF.
- Une fois le programme eBPF chargé, il peut être attaché à un événement spécifique du noyau, tel qu’un paquet réseau ou un appel système.
- Lorsque l’événement de noyau attaché se produit, il exécute automatiquement le programme eBPF. Le programme eBPF peut accéder aux données associées à l’événement et les modifier, en utilisant la programmation C standard, comme les bloops et les conditionnels.
- Une fois que le programme eBPF a traité les données, il peut renvoyer un résultat au noyau. Par exemple, un programme eBPF attaché à une interface réseau peut supprimer un paquet s’il répond à certains critères, ou un programme eBPF attaché à un appel système peut modifier les arguments transmis à l’appel avant de l’autoriser à continuer.
- Lorsque le programme eBPF n’est plus nécessaire, il peut être téléchargé à partir du noyau, libérant ainsi les ressources allouées au programme eBPF et garantissant qu’il ne s’exécutera plus lorsque l’événement de noyau attaché se produit.
Il est à noter que l’une des principales caractéristiques d’eBPF est ses garanties de sécurité. Les programmes eBPF s’exécutent sur une machine virtuelle restreinte au sein du noyau et ne peuvent pas accéder directement aux structures de données du noyau ou les modifier, ni provoquer des failles de sécurité ou des vulnérabilités. En outre, les programmes eBPF sont soumis à diverses vérifications d’exécution, telles que la vérification des limites et la vérification du type, pour s’assurer qu’ils ne violent pas la sécurité de la mémoire ou d’autres propriétés de sécurité.
Avantages de l’eBPF
La mise en œuvre de l’eBPF présente des avantages tels que :
- Vitesse et performances : eBPF est une solution universelle et efficace que les développeurs utilisent pour assurer les performances et la stabilité des systèmes.
- Faible intrusivité : Comme les programmes eBPF s’exécutent dans le noyau Linux, ils fonctionnent avec une surcharge minimale par rapport aux programmes traditionnels de l’espace utilisateur.
- Sécurité: eBPF visualise et explique les appels système, ce qui permet de contrôler les processus réseau.
- Commodité : La technologie nécessite une configuration minimale par rapport aux autres solutions afin que les développeurs puissent déployer rapidement leurs applications dans des environnements de production avec le moins d’effort possible.
- Traçabilité unifiée : Avec eBPF, les données sur les performances des applications et services basés sur Linux peuvent être collectées via des programmes s’exécutant dans l’espace noyau. Ces données peuvent être utilisées pour résoudre les problèmes de performances.
- Programmabilité : Les développeurs utilisant eBPF peuvent écrire de nouvelles fonctionnalités qui n’auraient pas pu être exécutées auparavant en raison de limitations techniques ou de problèmes de sécurité. Avec eBPF, vous pouvez écrire des applications qui tirent parti de l’accélération matérielle sur des périphériques intégrés tels que Raspberry Pi (un micro-ordinateur peu coûteux qui peut être inséré dans un moniteur ou un téléviseur) ou d’autres systèmes basés sur ARM, qui est une architecture de processeur largement utilisée sur les appareils mobiles, les serveurs et les systèmes embarqués.
- Expressivité : Avec eBPF, il est possible d’extraire des données d’observabilité de sécurité qui aident les développeurs d’applications à suivre les applications, à fournir des informations pour la résolution des problèmes de performance, à appliquer la sécurité lors de l’exécution des applications et des conteneurs, entre autres.
Meilleures pratiques eBPF
- Compilation avec LLVM et Clang : Clang est utilisé pour compiler des programmes eBPF à partir du code C et s’appuie sur LLVM comme backend pour assurer la correction et la sécurité.
- Utilisation de la boîte à outils BCC : BCC est un ensemble d’outils pour créer des programmes efficaces de manipulation et de suivi du noyau et comprend des exemples utiles.
- Utilisation des fonctions auxiliaires d’eBPF : Utilisation de la connexion de petits programmes efficaces à plusieurs hooks du noyau pour obtenir une visibilité et une supervision des capacités, assurer la sécurité du réseau et des conteneurs/microservices des applications, ainsi que détecter/prévenir les intrusions et renforcer les politiques de sécurité.
- Utilisation de cartes pour partager des données : Les cartes eBPF peuvent être partagées entre des exécutions consécutives de programmes, entre le noyau et l’espace utilisateur ou, selon le cas d’utilisation, entre différents programmes eBPF, quelles que soient les interfaces auxquelles ils sont connectés.
- Supervision des limites de ressources : La supervision de la capacité des ressources permet de mettre en œuvre des actions préventives de la part des employés informatiques.
- Validation des entrées utilisateur : Des programmes eBPF personnalisés peuvent être créés pour faire respecter les contrôles d’accès, réguler l’utilisation des ressources et protéger les composants sensibles du système contre les manipulations.
- Maintenance à jour du noyau : Les fabricants de matériel font des progrès constants, de sorte que la mise à niveau permet d’intégrer de nouvelles technologies, en plus d’améliorer les performances.
- Utilisation des bibliothèques et des frameworks eBPF : Les frameworks et les bibliothèques de supervision eBPF permettent un suivi efficace des processus et des événements réseau, ainsi que l’analyse des symboles de débogage du noyau.
- Documentation du code : La documentation aide les développeurs à suivre les applications et à garder une trace de la résolution des problèmes de performance.
Inconvénients de l’eBPF
- Limitations de portabilité : L’utilisation d’eBPF pour effectuer un traitement intensif de CPU ou de paquet par paquet ne serait pas efficace car il faudrait construire une structure et effectuer une recherche pour chaque paquet, ce qui peut devenir coûteux.
- Limitations des programmes sandboxed : Une chose est sûre : eBPF n’a pas été conçu pour la supervision de la sécurité. Les programmes sandboxed ont leurs limites :
- Mémoire : Ils fonctionnent dans un espace mémoire restreint.
- Syscall : Ils ne peuvent effectuer que des syscalls spécifiques autorisés par le vérificateur eBPF.
- Accès aux structures de données du noyau : L’accès direct aux structures de données du noyau est restreint.
- Accès au système de fichiers : Ils ne peuvent pas lire ou écrire des fichiers directement.
Cas d’utilisation d’eBPF
- Supervision du système en temps réel. Contrairement aux indicateurs et compteurs statiques, eBPF permet la génération d’événements de visibilité ainsi que la collecte et l’agrégation de métriques personnalisées en temps réel. Cela augmente la profondeur de la visibilité qui peut être atteinte et réduit considérablement la surcharge globale du système.
- Sécurité informatique. eBPF permet de détecter et d’enquêter sur les anomalies dans les opérations, telles qu’un processus inhabituel démarré dans un système, et de suivre leur comportement pour déterminer quelles ressources tentent d’accéder ou quelles données sont transmises sur le réseau. De cette façon, eBPF complète et aide à soutenir d’autres processus dans le cadre des systèmes de sécurité qui protègent votre serveur.
- Réseaux. La possibilité d’inspecter tous les événements de réseau et les flux de trafic réseau entrant et sortant d’un système et de déterminer quels processus interagissent avec eux aide les administrateurs à résoudre les problèmes de réseau. Il fournit également un contexte qui peut être utile lorsque l’on cherche à déterminer si un problème de performance avec une application est causé par un événement réseau ou par l’application elle-même.
- Supervision des performances des applications. Des mesures de performance peuvent être calculées pour des applications, des microservices et des processus individuels de manière granulaire. Cela permet d’établir des profils de performance et de suivre en permanence les anomalies. Avec eBPF, il n’est pas nécessaire de déployer et de configurer des agents pour suivre chaque application ou processus.
- Polyvalence. Contrairement aux outils de supervision traditionnels, principalement axés sur la consommation de ressources système, le profilage eBPF fournit une compréhension granulaire de la quantité d’UCT, de mémoire et de ressources réseau consommée par une application ou un processus spécifique. Ces données détaillées permettent d’identifier les applications gourmandes en ressources, de définir les optimisations possibles et de prendre des décisions éclairées sur la migration des charges de travail.
Applications d’eBPF en observabilité
Accès aux événements de bas niveau du système : eBPF permet la collecte et l’agrégation dans le noyau de métriques personnalisées, à l’aide d’événements de visibilité et de structures de données provenant de diverses sources sans avoir à exporter d’échantillons.
Applications en sécurité, performance et mise en réseau : eBPF est utilisé pour fournir des moyens plus efficaces et plus sûrs de gérer les applications conteneurisées et d’analyser les performances des systèmes. Par exemple :
- Le projet Falco utilise eBPF pour assurer la sécurité au moment de l’exécution pour les applications en conteneurs.
- Le projet Cilium utilise eBPF pour effectuer le filtrage réseau, l’équilibrage de charge et même la sécurité dans l’espace du noyau, ce qui améliore l’efficacité des applications conteneurisées.
- BCC (BPF Compiler Collection) est un ensemble d’outils et de bibliothèques utilisés par eBPF pour le suivi et l’analyse des performances des systèmes Linux.
Comment démarrer avec eBPF
Maintenant que vous savez comment tirer parti de eBPF, de ses avantages et de ses considérations, il ne vous reste plus qu’à partager avec vous quelques recommandations pour commencer à utiliser eBPF. L’enrichissement d’eBPF fait partie des contributions de développeurs indépendants, nous pouvons donc vous fournir des liens vers des ressources et des outils dont vous pouvez profiter :
- BCC Toolkit, avec des outils et des exemples d’utilisation d’eBPF et de ressources de programmation en C et Python.
- Page d’infrastructure eBPF, où vous pouvez trouver les compilateurs de l’infrastructure LLVM et GCC, y compris les codes de programme, les contributions sur les lacunes à résoudre et les blogs de support, entre autres.
- Cas de réussite mondiaux d’utilisation de eBPF, tels que Google, Netflix, Android, Cloudflare, Android, Microsoft, entre autres.
- Linux Foundation, où vous trouverez des informations intéressantes sur la communauté impliquée dans l’évolution d’eBPF et de son écosystème. Vous trouverez également dans le rapport State of eBPF un peu de son histoire et de ses perspectives d’avenir.
Au-delà des limites, au-delà des attentes