[Revisión de actividad] Comprender eBPF comienza con estos ejemplos

El octavo Elixir Meetup patrocinado por Tubi finalizó con éxito a finales de mayo.Tres usuarios senior de Elixir,  Horvo , Scott  y Yang Miao, compartieron las aplicaciones y prácticas relevantes de Elixir con más de 660 entusiastas de la programación funcional en línea y fuera de línea. Este artículo revisa el intercambio "La comprensión de eBPF comienza a partir de estos ejemplos" presentado por Yang Miao.

Bienvenido a prestar atención a la cuenta pública de Bitu Technology para conocer la información y las actividades más recientes de Elixir.


¿Qué es eBPF?

eBPF es una tecnología en el kernel de Linux, y su nombre completo es Extended Berkeley Packet Filter. El BPF clásico (Berkeley Packet Filter) se diseñó originalmente para el filtrado de tráfico de red (por ejemplo, el comando tcpdump usa BPF para el filtrado de paquetes). Classic BPF apareció en 1992, se fusionó con el sistema Linux en 1997 y no hubo desarrollos significativos durante muchos años después de eso.

A principios de 2014, Alexei Starovoitov implementó eBPF. A diferencia del BPF clásico, eBPF es una extensión más avanzada, como la expansión del conjunto de instrucciones, la introducción de soporte de lenguaje de alto nivel, la introducción de mecanismos de seguridad, JIT, Maps, etc. Por lo tanto, eBPF tiene una gama más amplia de escenarios de aplicación, como análisis de rendimiento, auditoría de seguridad, seguimiento de aplicaciones, etc.

Principios de eBPF

eBPF funciona insertando una máquina virtual en el kernel que puede ejecutar código seguro y restringido. Estos códigos se pueden usar para filtrar y modificar paquetes de red, monitorear y analizar el rendimiento del sistema, controlar el comportamiento de las aplicaciones y más.

El programa eBPF se basa en eventos y se ejecuta cuando el kernel o la aplicación pasan por un cierto punto de conexión, es decir, se puede cargar y ejecutar a través de herramientas y API en el espacio del usuario, o se puede ejecutar automáticamente a través de disparadores como eventos del kernel y tráfico de red.

Si la definición anterior de eBPF no es lo suficientemente intuitiva, simplemente podemos entenderla de esta manera: se le proporciona un punto de entrada donde puede colocar un fragmento de código que puede ejecutarse de manera segura en el núcleo para realizar algún procesamiento (con un procesamiento limitado de curso). Los amigos que han estudiado Java pueden pensar en AOP (es decir, Programación Orientada a Aspectos) al ver esto.El principio de eBPF es similar a Java AOP en pensamiento. AOP en Java nos permite agregar un "punto de corte" (generalmente un método, marcado con anotaciones) en el código comercial normal, y luego podemos agregar "lógica de aspecto" al "punto de corte".

Un ejemplo de un UDST

El nombre completo de USDT es Seguimiento definido estáticamente de Userland, es decir, seguimiento definido estáticamente en el espacio del usuario. Es un punto de seguimiento estático definido en un programa de espacio de usuario para recopilar y analizar datos de rendimiento e información de comportamiento del programa mientras se ejecuta. Muchos programas han agregado soporte para USDT, como Erlang, Ruby, Java, MySql, etc. Veamos un ejemplo de código para monitorear la recolección de basura de Erlang (este programa debe ejecutarse usando bpftrace, bpftrace es un lenguaje de alto nivel basado en eBPF, lo que facilita la escritura de programas eBPF):

usdt:beam.smp:gcminorstart
{
@start[srt(arg0)] = nsecs;
}
usdt:beam.smp:gcminorend
{
@usecs= hist((nsecs -@start[str(arg0)]) / 1000);
delete(@start[str(arg0)]);
}
END
{
clear(@start);
}

Explique estos códigos:

usdt:beam.smp:gc_minor__start: indica el punto de sondeo activado al comienzo de la recolección de elementos no utilizados, que se usa para registrar la marca de tiempo actual (en nanosegundos)

· usdt:beam.smp:gc_minor__end: indica el punto de detección activado al final de la recolección de elementos no utilizados, que se utiliza para calcular el tiempo que lleva el proceso de recolección de elementos no utilizados. Entre ellos, @start y @usecs son mapas BPF para guardar y estadísticas. @start es una matriz asociativa indexada por arg0 de tipo cadena, que contiene la marca de tiempo cuando comienza cada recolección de elementos no utilizados. @usecs es un histograma (histograma) que se usa para registrar el tiempo (en microsegundos) del proceso de recolección de basura y dividirlo en múltiples intervalos para estadísticas y agregación

· La función final calcula la diferencia de la marca de tiempo, hace que el proceso de recolección de elementos no utilizados consuma mucho tiempo y lo registra en @usecs, y la llamada de eliminación elimina la marca de tiempo de inicio de la recolección de elementos no utilizados actual de la matriz @start

· En el bloque final, use la función borrar para borrar la matriz @start para el próximo monitoreo de recolección de basura.

Introducción a los uprobes

En el ejemplo anterior de USDT, aprendimos que el programa de usuario debe tener un gancho antes de que podamos hacer cosas, es decir, los puntos de detección están predefinidos. Si el usuario no lo proporciona, también podemos utilizar uprobes para el seguimiento y la detección.

Los Uprobes son seguimientos dinámicos a nivel de usuario que permiten a los desarrolladores insertar sondeos en la entrada y salida de funciones arbitrarias en programas de espacio de usuario para recopilar información sobre llamadas a funciones y devoluciones en tiempo de ejecución. Estas sondas se pueden utilizar para la depuración, la creación de perfiles de rendimiento y la auditoría de seguridad. El principio es insertar un punto de interrupción en la instrucción del código. Cuando se ejecuta esta instrucción, se puede transferir al controlador que especificamos para su ejecución, y luego se pueden realizar operaciones como lectura y modificación de parámetros en el controlador. En toda la arquitectura de rastreo eBPF, la posición de los uprobes es la siguiente:

Auto-Instrumentation for Go es un proyecto basado en uprobes que se puede usar para rastrear aplicaciones Go. El siguiente código demuestra la lectura de una solicitud Go:

Introducción a los ganchos de control de tráfico (TC)

Traffic Control (TC) es un mecanismo de control de tráfico de red en el kernel de Linux, que se utiliza para controlar el límite de velocidad, el retraso y la pérdida de paquetes del tráfico de red. Los ganchos TC, como su nombre lo indica, son ganchos TC Podemos insertar programas eBPF cuando los datos de la red pasan a través de la cadena TC para lograr propósitos como el monitoreo.

El marco de TC contiene muchos componentes, incluido el clasificador (Classifier), la cola (Queue), el programador de colas (Disciplina de colas), etc. Los Hooks de TC pueden actuar en cualquier nodo de estos componentes, el más utilizado es el programador de colas (Disciplina de colas) , como se muestra en la siguiente figura:

Por lo general, nuestra aplicación de software tendrá muchos módulos y la solicitud de un usuario pasará por varias llamadas de servicio. Si queremos crear un flujo de solicitud, ¿qué debemos hacer? El método más común es TraceId, que transmite continuamente un TraceId para obtener un flujo de solicitud. Sin embargo, este enfoque requiere la modificación del código.Si hay muchas aplicaciones, o incluso varios idiomas, el costo de modificación y mantenimiento será alto. Si nos sumergimos al siguiente nivel y usamos TC Hook para hacer trucos, el costo puede reducirse considerablemente (alrededor de N veces M a M), y la lógica se muestra en la siguiente figura:

El siguiente código demuestra cómo usar la solicitud HTTP eBPF Hook (el programa debe ejecutarse usando bcc, bcc es un conjunto de herramientas que proporciona una API más fácil de usar, lo que facilita la escritura de programas eBPF):

Como se muestra en el código anterior, cuelgue el código eBPF en el kernel para ejecutarlo a través de TC (el sniff.c anterior se ejecuta en el kernel), lea los datos en el kernel y transfiera los datos al programa del usuario, y el usuario programa puede analizar los datos originales. La salida del programa anterior es la siguiente:

interacción maravillosa

Preocupaciones de seguridad sobre eBPF

En el sitio de Elixir Meetup, vimos el poder de eBPF, que puede ejecutar código en el kernel; naturalmente, también estamos preocupados por sus problemas de seguridad. ¿Cómo eBPF garantiza la seguridad y qué hacer si entra en pánico?

En primer lugar, la mayoría de los programas eBPF necesitan los permisos correspondientes para cargar, como root, CAP_EBPF. En segundo lugar, el Kernel usará el verificador para verificar, y el verificador garantizará la seguridad de la memoria de eBPF y el programa finalizará (terminación), y solo podrá llamar al método especificado, como se muestra en la siguiente figura:

Algunos proyectos de código abierto sobre eBPF

eBPF ha sido llamado el mayor cambio en el sistema operativo en las últimas décadas. De hecho, muchas empresas tienen prácticas de eBPF, y hay muchos proyectos de código abierto sobre eBPF en la comunidad. Aquí están algunas:

· Katran [Red - Balanceador de carga de capa 4]: el balanceador de carga de capa 4 de alto rendimiento de código abierto de Facebook. Katran es una biblioteca Cpp y un programa eBPF para crear un plano de reenvío de equilibrio de carga de capa 4 de alto rendimiento

Cilium [red/seguridad/observabilidad]: proyecto de código abierto isovalente que proporciona redes, seguridad y observabilidad impulsadas por eBPF. Está diseñado específicamente para llevar los beneficios de BPF al mundo de Kubernetes para abordar los nuevos requisitos de escalabilidad, seguridad y visibilidad de las cargas de trabajo de contenedores.

· BCC [Herramientas de desarrollo]: es un kit de herramientas de manipulación y seguimiento del kernel eficiente basado en eBPF, que incluye varias herramientas y ejemplos útiles de línea de comandos. BCC simplifica la escritura de programas BPF en C, incluye un contenedor alrededor de LLVM y enlaces frontales para Python y Lua

· bmc-cache(memcache+eBPF): a través de eBPF, el rendimiento de Memcached aumenta 18 veces. En resumen, bmc-cache usa eBPF para omitir el kernel y, al mismo tiempo, permite que el rendimiento de Memcached crezca mejor con el aumento de la CPU.

Si estás interesado en eBPF y quieres aprender e investigar en profundidad, también te recomiendo leer este blog técnico www.ebpf.top/ .

El intercambio anterior proviene de la audiencia en vivo Deming, ¡gracias por tu contribución a la comunidad de Elixir!

Otros casos de aplicación de Elixir en Tubi

Uso de Elixir/OTP para construir una plataforma de procesamiento multimedia E2E
Aplicación de ideas de Ruby en proyectos de Elixir
Un problema de rendimiento oculto en el código base de Elixir durante 7 años

¡Únete a Tubi para crecer y ser más fuertes juntos!

Trabajos calientes: https://tubi.tech/careers/

Cuenta oficial de WeChat: [Revisión de actividad] Comprender eBPF comienza con estos ejemplos

Supongo que te gusta

Origin blog.csdn.net/weixin_49193714/article/details/131576224
Recomendado
Clasificación