Capítulo 1. ¿Qué es el eBPF y por qué es importante?
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
eBPF es una tecnología revolucionaria del núcleo que permite a los desarrolladores escribir código personalizado que puede cargarse en el núcleo de forma dinámica, cambiando la forma en que éste se comporta. (No te preocupes si no estás seguro de lo que es el núcleo: hablaremos de ello en breve en este capítulo).
Esto permite una nueva generación de herramientas de red, observabilidad y seguridad de alto rendimiento. Y como verás, si quieres instrumentar una aplicación con estas herramientas basadas en eBPF, no necesitas modificar ni reconfigurar la aplicación en modo alguno, gracias al punto de ventaja de eBPF dentro del núcleo.
Algunas de las cosas que puedes hacer con eBPF son:
-
Seguimiento del rendimiento de prácticamente cualquier aspecto de un sistema
-
Redes de alto rendimiento, con visibilidad integrada
-
Detectar y (opcionalmente) prevenir actividades maliciosas
Hagamos un breve recorrido por la historia del eBPF, empezando por el Filtro de Paquetes Berkeley.
Las raíces del eBPF: El Filtro de Paquetes Berkeley
Lo que hoy llamamos "eBPF" tiene sus raíces en el Filtro de Paquetes BSD, descrito por primera vez en 1993 en un documento1 escrito por el Laboratorio Nacional Lawrence Berkeley Steven McCanne y Van Jacobson. Este documento habla de una pseudomáquina que puede ejecutar filtros, que son programas escritos para determinar si se debe aceptar o rechazar un paquete de red. Estos programas se escribieron en el conjunto de instrucciones BPF, un conjunto de instrucciones de 32 bits de uso general que se parece mucho al lenguaje ensamblador. He aquí un ejemplo tomado directamente de ese documento:
ldh [12] jeq #ETHERTYPE IP, L1, L2 L1: ret #TRUE L2: ret #0
Este pequeño trozo de código filtra los paquetes que no son paquetes de Protocolo de Internet (IP). La entrada de este filtro es un paquete Ethernet, y la primera instrucción (ldh
) carga un valor de 2 bytes que comienza en el byte 12 de este paquete. En la siguiente instrucción (jeq
) ese valor se compara con el valor que representa un paquete IP. Si coincide, la ejecución salta a la instrucción etiquetada L1
, y el paquete se acepta devolviendo un valor distinto de cero (identificado aquí como #TRUE
). Si no coincide, el paquete no es un paquete IP y se rechaza devolviendo 0
.
Puedes imaginar (o, de hecho, consultar el documento para encontrar ejemplos de) programas de filtrado más complejos que tomen decisiones basadas en otros aspectos del paquete. Es importante destacar que el autor del filtro puede escribir sus propios programas personalizados para que se ejecuten dentro del núcleo, y éste es el núcleo de lo que permite eBPF.
BPF viene de "Berkeley Packet Filter" (filtro de paquetes Berkeley), y se introdujo por primera vez en Linux en 1997, en la versión 2.1.75 del núcleo,2 donde se utilizaba en la utilidad tcpdump como una forma eficaz de capturar los paquetes que se iban a rastrear.
Avance rápido hasta 2012, cuando se introdujo seccomp-bpf en la versión 3.5 del núcleo. Esto permitió el uso de programas BPF para tomar decisiones sobre si permitir o denegar a las aplicaciones del espacio de usuario realizar llamadas al sistema. Exploraremos esto con más detalle en el Capítulo 10. Este fue el primer paso en la evolución de BPF desde el estrecho ámbito del filtrado de paquetes a la plataforma de uso general que es hoy. A partir de este momento, ¡las palabras filtro de paquetesen el nombre empezaron a tener menos sentido!
De BPF a eBPF
BPF evolucionó a lo que llamamos "BPF ampliado" o "eBPF" a partir de la versión 3.18 del núcleo en 2014. Esto supuso varios cambios significativos:
-
El conjunto de instrucciones BPF se revisó por completo para que fuera más eficiente en máquinas de 64 bits, y el intérprete se reescribió por completo.
-
Se introdujeron los mapas eBPF, que son estructuras de datos a las que pueden acceder los programas BPF y las aplicaciones del espacio de usuario, permitiendo compartir información entre ellos. Aprenderás sobre los mapas en el Capítulo 2.
-
La llamada al sistema
bpf()
se añadió para que los programas del espacio de usuario puedan interactuar con los programas eBPF del núcleo. Leerás sobre esta llamada al sistema en el Capítulo 4. -
Se han añadido varias funciones de ayuda BPF. Verás algunos ejemplos en el Capítulo 2 y más detalles en el Capítulo 6.
-
El verificador eBPF se añadió para garantizar que los programas eBPF se ejecutan con seguridad. Esto se trata en el Capítulo 6.
Esto sentó las bases de eBPF, ¡pero el desarrollo no se ralentizó! Desde entonces, eBPF ha evolucionado considerablemente.
La evolución del eBPF a los sistemas de producción
Una función de llamada kprobes (sondas del kernel) existía en el kernel de Linux desde 2005, y permitía colocar trampas en casi cualquier instrucción del código del kernel. Los desarrolladores podían escribir módulos del núcleo que adjuntaran funciones a las kprobes con fines de depuración o medición del rendimiento.3
En 2015 se añadió la posibilidad de adjuntar programas eBPF a las kprobes, lo que supuso el punto de partida de una revolución en la forma de realizar el rastreo en los sistemas Linux. Al mismo tiempo, se empezaron a añadir ganchos dentro de la pila de red del núcleo, lo que permitió a los programas eBPF ocuparse de más aspectos de la funcionalidad de red. Veremos más de esto en el Capítulo 8.
En 2016, ya se utilizaban herramientas basadas en eBPF en sistemas de producción. El trabajo de Brendan Gregg sobre trazado en Netflix se hizo ampliamente conocido en los círculos de infraestructuras y operaciones, al igual que su afirmación de que eBPF "aporta superpoderes a Linux". Ese mismo año, se anunció el proyecto Cilium, que fue el primer proyecto de redes en utilizar eBPF para sustituir toda la ruta de datos en entornos de contenedores.
Al año siguiente, Facebook (ahora Meta) convirtió Katran en un proyecto de código abierto. Katran, un equilibrador de carga de capa 4, satisfacía la necesidad de Facebook de una solución rápida y altamente escalable. Todos y cada uno de los paquetes enviados a Facebook.com desde 2017 han pasado por eBPF/XDP.4 Para mí, personalmente, éste fue el año que encendió mi entusiasmo por las posibilidades que ofrece esta tecnología, después de ver la charla de Thomas Grafsobre eBPF y el proyecto Cilium en la DockerCon de Austin (Texas).
En 2018, eBPF se convirtió en un subsistema independiente dentro del núcleo Linux, con Daniel Borkmann de Isovalent y Alexei Starovoitov de Meta como sus mantenedores (más tarde se les unió Andrii Nakryiko, también de Meta). Ese mismo año se introdujo el Formato de Tipo BPF (BTF), que hace que los programas eBPF sean mucho más portables. Exploraremos esto en el Capítulo 5.
En el año 2020 se introdujo el LSM BPF, que permite conectar programas eBPF a la interfaz del kernel del Módulo de Seguridad Linux (LSM). Esto indicaba que se había identificado un tercer caso de uso importante para eBPF: quedó claro que eBPF es una gran plataforma para las herramientas de seguridad, además de para la creación de redes y la observabilidad.
A lo largo de los años, las capacidades del eBPF han crecido sustancialmente, gracias al trabajo de más de 300 desarrolladores del núcleo y de muchos colaboradores de las herramientas de espacio de usuario asociadas (como bpftool
, que conoceremos en el Capítulo 3), compiladores y bibliotecas de lenguajes de programación. Antes, los programas estaban limitados a 4.096 instrucciones, pero ese límite ha crecido hasta 1 millón de instrucciones verificadas5 y ha pasado a ser irrelevante gracias a la compatibilidad con las llamadas de cola y las llamadas a funciones (que verás en los Capítulos 2 y 3).
Nota
Para profundizar en la historia de eBPF, ¿quién mejor que los mantenedores que han estado trabajando en él desde el principio?
Alexei Starovoitov hizo una presentación fascinante sobre la historia de eBPF desde sus raíces en las redes definidas por software (SDN). En esta charla, habla de las estrategias utilizadas para conseguir que los primeros parches de eBPF fueran aceptados en el núcleo y revela que el cumpleaños oficial de eBPF es el 26 de septiembre de 2014, que marcó la aceptación del primer conjunto de parches que cubrían el verificador, la llamada al sistema BPF y los mapas.
Daniel Borkmann también ha hablado de la historia de BPF y de su evolución para dar soporte a las funciones de red y rastreo. Recomiendo encarecidamente su charla "eBPF y Kubernetes: Little Helper Minions for Scaling Microservices", que está llena de interesantes pepitas de información.
Nombrar es difícil
Las aplicaciones de eBPF van tan lejos del filtrado de paquetes que el acrónimo ya no tiene sentido, y se ha convertido en un término independiente. Y como todos los núcleos Linux de uso generalizado en la actualidad son compatibles con las partes "ampliadas", los términos eBPF y BPF se utilizan en gran medida indistintamente. En el código fuente del núcleo y en la programación eBPF, la terminología común es BPF. Por ejemplo, como veremos en el Capítulo 4, la llamada al sistema para interactuar con eBPF es bpf()
, las funciones de ayuda empiezan por bpf_
, y los distintos tipos de programas (e)BPF se identifican con nombres que empiezan por BPF_PROG_TYPE
. Fuera de la comunidad del núcleo, el nombre "eBPF" parece haber calado, por ejemplo, en el sitio de la comunidad ebpf.io y en el nombre de la Fundación eBPF.
El núcleo Linux
Para entender el eBPF necesitarás un sólido conocimiento de la diferencia entre el núcleo y el espacio de usuario en Linux. Cubrí esto en mi informe "¿Qué es eBPF?"6 y he adaptado parte de ese contenido para los siguientes párrafos.
El núcleo Linux es la capa de software entre tus aplicaciones y el hardware en el que se ejecutan. Las aplicaciones se ejecutan en una capa sin privilegios llamada espacio de usuario, que no puede acceder directamente al hardware. En su lugar, una aplicación realiza peticiones utilizando la interfaz de llamada al sistema (syscall) para solicitar al núcleo que actúe en su nombre. Ese acceso al hardware puede implicar leer y escribir en archivos, enviar o recibir tráfico de red, o incluso simplemente acceder a la memoria. El núcleo también es responsable de coordinar los procesos concurrentes, permitiendo que muchas aplicaciones se ejecuten a la vez. Esto se ilustra en la Figura 1-1.
Como desarrolladores de aplicaciones, normalmente no utilizamos directamente la interfaz de llamada al sistema, porque los lenguajes de programación nos proporcionan abstracciones de alto nivel y bibliotecas estándar que son interfaces más fáciles de programar. Como resultado, mucha gente ignora felizmente cuánto está haciendo el núcleo mientras se ejecutan nuestros programas. Si quieres hacerte una idea de la frecuencia con la que se invoca al núcleo, puedes utilizar la utilidad strace
para mostrar todas las llamadas al sistema que realiza una aplicación.
He aquí un ejemplo, en el que utilizar cat
para hacer eco de la palabra hola en la pantalla implica más de 100 llamadas al sistema:
$ strace -c echo "hello" hello % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 24.62 0.001693 56 30 12 openat 17.49 0.001203 60 20 mmap 15.92 0.001095 57 19 newfstatat 15.66 0.001077 53 20 close 10.35 0.000712 712 1 execve 3.04 0.000209 52 4 mprotect 2.52 0.000173 57 3 read 2.33 0.000160 53 3 brk 2.09 0.000144 48 3 munmap 1.11 0.000076 76 1 write 0.96 0.000066 66 1 1 faccessat 0.76 0.000052 52 1 getrandom 0.68 0.000047 47 1 rseq 0.65 0.000045 45 1 set_robust_list 0.63 0.000043 43 1 prlimit64 0.61 0.000042 42 1 set_tid_address 0.58 0.000040 40 1 futex ------ ----------- ----------- --------- --------- ---------------- 100.00 0.006877 61 111 13 total
Como las aplicaciones dependen tanto del núcleo, podemos aprender mucho sobre cómo se comporta una aplicación si podemos observar sus interacciones con el núcleo. Con eBPF podemos añadir instrumentación en el núcleo para obtener esta información.
Por ejemplo, si eres capaz de interceptar la llamada del sistema para abrir archivos, podrás ver exactamente a qué archivos accede cualquier aplicación. Pero, ¿cómo podrías hacer esa interceptación? Pensemos en lo que supondría modificar el núcleo, añadiendo nuevo código para crear algún tipo de salida cada vez que se invoque esa llamada al sistema.
Añadir nuevas funciones al núcleo
El núcleo de Linux es complejo, con unos 30 millones de líneas de código en el momento de escribir estas líneas.7 Hacer un cambio en cualquier base de código requiere cierta familiaridad con el código existente, así que, a menos que ya seas un desarrollador del núcleo, es probable que esto suponga un reto.
Además, si quieres contribuir con tu cambio en el flujo ascendente, te enfrentarás a un reto que no es puramente técnico. Linux es un sistema operativo de uso general, que se utiliza en todo tipo de entornos y circunstancias. Esto significa que si quieres que tu cambio forme parte de una versión oficial de Linux, no se trata simplemente de escribir un código que funcione. El código tiene que ser aceptado por la comunidad (y más concretamente por Linus Torvalds, creador y principal desarrollador de Linux) como un cambio que redundará en el mayor bien de todos. Esto no es un hecho: sólo un tercio de los parches del núcleo enviados son aceptados.8
Supongamos que has descubierto un buen enfoque técnico para interceptar la llamada del sistema para abrir archivos. Tras algunos meses de discusión y un duro trabajo de desarrollo por tu parte, imaginemos que el cambio se acepta en el núcleo. ¡Estupendo! Pero ¿cuánto tiempo pasará hasta que llegue a las máquinas de todo el mundo?
Cada dos o tres meses se publica una nueva versión del núcleo de Linux, pero incluso cuando un cambio ha llegado a una de estas versiones, aún falta algún tiempo para que esté disponible en los entornos de producción de la mayoría de la gente. Esto se debe a que la mayoría de nosotros no utilizamos directamente el núcleo de Linux, sino distribuciones de Linux como Debian, Red Hat, Alpine y Ubuntu, que empaquetan una versión del núcleo de Linux con otros componentes. Es muy posible que tu distribución favorita utilice una versión del núcleo de hace varios años.
Por ejemplo, muchos usuarios empresariales emplean Red Hat Enterprise Linux (RHEL). En el momento de escribir esto, la versión actual es RHEL 8.5, de noviembre de 2021, y utiliza la versión 4.18 del núcleo Linux. Este núcleo se lanzó en agosto de 2018.
Como se ilustra en la viñeta de la Figura 1-2, se tarda literalmente años en conseguir que una nueva funcionalidad pase de la fase de idea al núcleo Linux de un entorno de producción.9
Módulos del núcleo
Si no quieres esperar años a que tu cambio llegue al núcleo, hay otra opción. El núcleo Linux se diseñó para aceptar módulos del núcleo, que pueden cargarse y descargarse bajo demanda. Si quieres cambiar o ampliar el comportamiento del núcleo, escribir un módulo es sin duda una forma de hacerlo. Un módulo del núcleo puede distribuirse para que otros lo utilicen independientemente de la versión oficial del núcleo Linux, por lo que no tiene que ser aceptado en la base de código principal.
El mayor reto aquí es que esto sigue siendo programación completa del núcleo. Históricamente, los usuarios han sido muy cautelosos a la hora de utilizar módulos del núcleo, por una sencilla razón: si el código del núcleo falla, se cae la máquina y todo lo que se ejecuta en ella. ¿Cómo puede un usuario confiar en que es seguro ejecutar un módulo del núcleo?
Ser "seguro de ejecutar" no sólo significa no bloquearse: el usuario quiere saber si un módulo del núcleo es seguro desde el punto de vista de la seguridad. ¿Incluye vulnerabilidades que podría explotar un atacante? ¿Confiamos en que los autores del módulo no introduzcan código malicioso en él? Como el núcleo es código privilegiado, tiene acceso a todo lo que hay en la máquina, incluidos todos los datos, por lo que un código malicioso en el núcleo sería un serio motivo de preocupación. Esto también se aplica a los módulos del núcleo.
La seguridad del núcleo es una razón importante por la que las distribuciones de Linux tardan tanto en incorporar nuevas versiones. Si otras personas han estado utilizando una versión del núcleo en diversas circunstancias durante meses o años, esto debería haber eliminado los problemas. Los responsables de la distribución pueden tener cierta confianza en que el núcleo que envían a sus usuarios/clientes está reforzado,es decir, es seguro de ejecutar.
eBPF ofrece un enfoque muy diferente de la seguridad: el verificador eBPF, que garantiza que un programa eBPF sólo se carga si es seguro ejecutarlo: no bloqueará la máquina ni la encerrará en un bucle difícil, y no permitirá que se pongan en peligro los datos. Trataremos el proceso de verificación con más detalle en el Capítulo 6.
Carga dinámica de programas eBPF
Los programas eBPF pueden cargarse y eliminarse del núcleo de forma dinámica. Una vez que se adjuntan a un evento, serán activados por ese evento independientemente de lo que haya provocado que se produzca ese evento. Por ejemplo, si adjuntas un programa a la llamada al sistema para abrir archivos, se activará siempre que cualquier proceso intente abrir un archivo. No importa si ese proceso ya se estaba ejecutando cuando se cargó el programa. Esto es una gran ventaja en comparación con actualizar el núcleo y luego tener que reiniciar la máquina para utilizar su nueva funcionalidad.
Esto nos lleva a uno de los grandes puntos fuertes de la observabilidad o de las herramientas de seguridad que utilizan eBPF: obtienen al instante visibilidad sobre todo lo que ocurre en la máquina. En entornos que ejecutan contenedores, eso incluye visibilidad sobre todos los procesos que se ejecutan dentro de esos contenedores, así como en la máquina anfitriona. Profundizaré en las consecuencias de esto para las Implementaciones nativas en la nube más adelante en este capítulo.
Además, como se ilustra en la Figura 1-3, la gente puede crear nuevas funcionalidades del núcleo muy rápidamente a través de eBPF sin necesidad de que todos los demás usuarios de Linux acepten los mismos cambios.
Alto rendimiento de los programas eBPF
Los programas eBPF son una forma muy eficaz de añadir instrumentación. Una vez cargado y compilado JIT (que verás en el Capítulo 3), el programa se ejecuta como instrucciones nativas de la máquina en la CPU. Además, no hay necesidad de incurrir en el coste de la transición entre el núcleo y el espacio de usuario (que es una operación costosa) para manejar cada evento.
El documento de 201810 que describe el eXpress Data Path (XDP) incluye algunas ilustraciones de los tipos de mejoras de rendimiento que eBPF permite en las redes. Por ejemplo, la implementación del enrutamiento en XDP "mejora el rendimiento en un factor de 2,5" en comparación con la implementación normal del núcleo Linux, y "XDP ofrece una ganancia de rendimiento de 4,3x sobre IPVS" para el equilibrio de carga.
Para el rastreo del rendimiento y la observabilidad de la seguridad, otra ventaja de eBPF es que los eventos relevantes pueden filtrarse dentro del núcleo antes de incurrir en los costes de enviarlos al espacio de usuario. Filtrar sólo determinados paquetes de red era, después de todo, el objetivo de la implementación original de BPF. Hoy en día, los programas eBPF pueden recopilar información sobre todo tipo de eventos en un sistema, y pueden utilizar filtros programáticos complejos y personalizados para enviar sólo el subconjunto de información relevante al espacio de usuario.
eBPF en entornos nativos de nube
Hoy en día, muchas organizaciones optan por no ejecutar aplicaciones ejecutando programas directamente en los servidores. En su lugar, muchas utilizan enfoques nativos de la nube: contenedores, orquestadores como Kubernetes o ECS, o enfoques sin servidor como Lambda, funciones en la nube, Fargate, etc. Todos estos enfoques utilizan la automatización para elegir el servidor donde se ejecutará cada carga de trabajo; en los enfoques sin servidor, ni siquiera sabemos qué servidor está ejecutando cada carga de trabajo.
Sin embargo, hay servidores implicados, y cada uno de esos servidores (ya sea una máquina virtual o una máquina bare-metal) ejecuta un núcleo. Cuando las aplicaciones se ejecutan en un contenedor, si se ejecutan en la misma máquina (virtual), comparten el mismo kernel. En un entorno Kubernetes, esto significa que todos los contenedores de todos los pods de un nodo determinado utilizan el mismo kernel. Cuando instrumentamos ese kernel con programas eBPF, todas las cargas de trabajo en contenedores de ese nodo son visibles para esos programas eBPF, como se ilustra en la Figura 1-4.
La visibilidad de todos los procesos del nodo, combinada con la capacidad de cargar programas eBPF dinámicamente, nos proporciona las verdaderas superpotencias de las herramientas basadas en eBPF en la computación nativa en la nube:
-
No necesitamos cambiar nuestras aplicaciones, ni siquiera la forma en que están configuradas, para instrumentarlas con herramientas eBPF.
-
En cuanto se carga en el núcleo y se adjunta a un evento, un programa eBPF puede empezar a observar procesos de aplicación preexistentes.
Contrasta esto con el modelo sidecar, que se ha utilizado para añadir funcionalidades como el registro, el rastreo, la seguridad y la funcionalidad de malla de servicios en las aplicaciones Kubernetes. En el enfoque sidecar, la instrumentación se ejecuta como un contenedor que se "inyecta" en cada pod de aplicación. Este proceso implica modificar el YAML que define los pods de aplicación, añadiendo la definición del contenedor sidecar. Este enfoque es ciertamente más cómodo que añadir la instrumentación en el código fuente de la aplicación (que es lo que teníamos que hacer antes del enfoque sidecar; por ejemplo, incluir una biblioteca de registro en nuestra aplicación y hacer llamadas a esa biblioteca en los puntos adecuados del código). Sin embargo, el enfoque sidecar tiene algunos inconvenientes:
-
El pod de aplicación tiene que reiniciarse para que se añada el sidecar.
-
Algo tiene que modificar el YAML de la aplicación. Por lo general, se trata de un proceso automatizado, pero si algo va mal, el sidecar no se añadirá, lo que significa que el pod no se instrumenta. Por ejemplo, una implementación puede estar anotada para indicar que un controlador de admisión debe añadir el sidecar YAML a la especificación del pod para esa implementación. Pero si la implementación no está etiquetada correctamente, el sidecar no se añadirá y, por tanto, no será visible para la instrumentación.
-
Cuando hay varios contenedores dentro de un pod, pueden alcanzar la disponibilidad en momentos diferentes, cuyo orden puede no ser predecible. El tiempo de arranque del pod puede ralentizarse significativamente por la inyección de sidecars, o peor aún, puede provocar condiciones de carrera u otras inestabilidades. Por ejemplo, la documentación de Open Service Mesh describe cómo los contenedores de aplicaciones tienen que ser resistentes a que todo el tráfico sea descartado hasta que el contenedor proxy Envoy esté listo.
-
Cuando la funcionalidad de red, como la malla de servicios, se implementa como sidecar, significa necesariamente que todo el tráfico hacia y desde el contenedor de la aplicación tiene que viajar a través de la pila de red en el núcleo para llegar a un contenedor proxy de red, lo que añade latencia a ese tráfico; esto se ilustra en la Figura 1-5. Hablaremos de cómo mejorar la eficiencia de la red con eBPF en el Capítulo 9.
Todas estas cuestiones son problemas inherentes al modelo de sidecar. Afortunadamente, ahora que eBPF está disponible como plataforma, tenemos un nuevo modelo que puede evitar estos problemas. Además, como las herramientas basadas en eBPF pueden ver todo lo que ocurre en una máquina (virtual), son más difíciles de esquivar para los malos actores. Por ejemplo, si un atacante consigue implementar una aplicación de minería de criptomonedas en uno de tus hosts, probablemente no tendrá la cortesía de instrumentarla con los sidecars que utilizas en las cargas de trabajo de tus aplicaciones. Si confías en una herramienta de seguridad basada en sidecares para evitar que las aplicaciones realicen conexiones de red inesperadas, esa herramienta no va a detectar la aplicación de minería que se conecta a su pool de minería si no se inyecta el sidecar. En cambio, la seguridad de red implementada en eBPF puede vigilar todo el tráfico de la máquina anfitriona, por lo que esta operación de minería de criptomonedas podría detenerse fácilmente. La capacidad de descartar paquetes de red por motivos de seguridad es algo a lo que volveremos en el Capítulo 8.
Resumen
Espero que este capítulo te haya dado una idea de por qué eBPF como plataforma es tan potente. Nos permite cambiar el comportamiento del kernel, proporcionándonos la flexibilidad necesaria para crear herramientas a medida o políticas personalizadas. Las herramientas basadas en eBPF pueden observar cualquier evento en el kernel y, por tanto, en todas las aplicaciones que se ejecuten en una máquina (virtual), estén o no en contenedores. Los programas eBPF también se pueden implementar dinámicamente, lo que permite cambiar el comportamiento sobre la marcha.
Hasta ahora hemos hablado de eBPF a un nivel relativamente conceptual. En el próximo capítulo lo haremos más concreto y exploraremos las partes constituyentes de una aplicación basada en eBPF.
1 "El Filtro de Paquetes BSD: Una nueva arquitectura para la captura de paquetes a nivel de usuario", de Steven McCanne y Van Jacobson.
2 Estos y otros detalles proceden de la presentación de Alexei Starovoitov en NetDev 2015, "BPF - in-kernel virtual machine".
3 Hay una buena descripción de cómo funcionan las kprobes en la documentación del núcleo.
4 Este maravilloso dato procede de la charla de Daniel Borkmann en la KubeCon 2020 titulada "eBPF y Kubernetes: Little Helper Minions for Scaling Microservices".
5 Para más detalles sobre el límite de instrucciones y el "límite de complejidad", consulta https://oreil.ly/0iVer.
6 Extracto de "¿Qué es eBPF?" de Liz Rice. Copyright © 2022 O'Reilly Media. Utilizado con permiso.
7 "Linux 5.12 Coming In At Around 28.8 Million Lines", Phoronix, marzo de 2021.
8 Jiang Y, Adams B, German DM. 2013. "¿Llegará mi parche? ¿Y con qué rapidez?" (2013). Según este trabajo de investigación, el 33% de los parches son aceptados, y la mayoría tardan entre tres y seis meses.
9 Afortunadamente, los parches de seguridad para la funcionalidad existente están disponibles más rápidamente.
10 Høiland-Jørgensen T, Brouer JD, Borkmann D, et al. "La ruta de datos eXpress: procesamiento rápido programable de paquetes en el núcleo del sistema operativo". Actas de la 14ª Conferencia Internacional sobre Experimentos y Tecnologías de Redes Emergentes (CoNEXT '18). Association for Computing Machinery; 2018:54-66.
Get Aprendizaje eBPF now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.