.png)
Asistí a la Cloud Native Security Con en Seattle con la plena intención de aprovechar el día de OTEL, para luego profundizar en el tema de la seguridad aplicada a las cargas de trabajo nativas en la nube en los días siguientes, culminando con el CTF como ejercicio profesional. Esto fue felizmente interrumpido por un nuevo entendimiento de eBPF, lo cual supuso una mejora muy necesaria para mis pantallas, carrera, cargas de trabajo y actitud, gracias a nuevos enfoques para resolver problemas relacionados con las cargas de trabajo.
Así que llegué a la "fiesta" de eBPF y desde entonces he estado asistiendo a clínica tras clínica sobre el tema. Aquí me gustaría "desempaquetar" eBPF como una solución técnica, mapeada directamente a lo que hacemos en la práctica (aunque no siempre coincida del todo), y recorrer eBPF a través de mis experimentos en el soporte de las cargas de trabajo de InterSystems IRIS, particularmente en Kubernetes, pero sin excluir las cargas de trabajo independientes.
.png)
Pasos de eBee con eBPF y Cargas de Trabajo de InterSystems IRIS
eBPF
eBPF (Extended Berkeley Packet Filter) es una increíble funcionalidad del kernel de Linux que implementa una máquina virtual dentro del espacio del kernel, lo que permite ejecutar aplicaciones en un entorno aislado de forma segura, con ciertas guías o restricciones. Estas aplicaciones pueden "mapear" datos al espacio de usuario para la observabilidad, rastreo, seguridad y redes. Lo veo como un "sniffer" del sistema operativo, donde tradicionalmente se asociaba con BPF y redes, y la versión extendida "olfatea" puntos de traza, procesos, planificación, ejecución y acceso a dispositivos de bloque. Si no te convence mi analogía de eBPF, aquí tienes una de los expertos:
"Lo que JavaScript es para el navegador, eBPF lo es para el kernel de Linux.
JavaScript os permite adjuntar funciones de callback a eventos en el DOM para añadir características dinámicas a vuestra página web. De manera similar, eBPF permite engancharse a eventos del kernel y extender su lógica cuando dichos eventos son activados. ¡Es como añadir dinamismo al funcionamiento del kernel!
Inmediatamente aplicable
SI; la siguiente métrica de Prometheus os parece imposible, emplead eBPF para vigilar los procesos que se supone deben estar presentes y monitorizad en banda a través del kernel.
# HELP iris_instance_status The thing thats down telling us its down.
# TYPE iris_instance_status gauge
iris_instance_status 0
SI; estáis cansados de rogar por un sidecar para obtener la observabilidad que necesitáis. Adiós, sidecars.
iris-sidecar:
resources:
requests:
memory: "2Mi"
cpu: "125m"
Donde
Una de las cosas más satisfactorias de cómo se aplica eBPF es dónde se ejecuta... en una máquina virtual dentro del kernel. Y gracias al Namespacing de Linux, os podéis imaginar lo potente que es en un entorno nativo de la nube, sin mencionar un kernel que corre en algún tipo de entorno virtualizado o en una máquina potente con hardware de alta gama.
.png)
Obligatorio "Hola Mundo".
Para aquellos de vosotros que os gusta probar las cosas por vosotros mismos y desde el "principio", os saludo con un obligatorio hello world o "Hola Mundo", ligeramente retorcido para ser un poco más "irisy". Sin embargo, es bien sabido que programar en eBPF no será una habilidad que se practique con frecuencia, sino que estará concentrada en quienes desarrollan el kernel de Linux o construyen herramientas de monitorización de próxima generación.
Yo uso Pop OS/Ubuntu, y aquí os dejo mi truco para adentrarse rápidamente en el mundo de eBPF en la versión 23.04:
sudo apt install -y zip bison build-essential cmake flex git libedit-dev \
libllvm15 llvm-15-dev libclang-15-dev python3 zlib1g-dev libelf-dev libfl-dev python3-setuptools \
liblzma-dev libdebuginfod-dev arping netperf iperf libpolly-15-dev
git clone https://github.com/iovisor/bcc.git
mkdir bcc/build; cd bcc/build
cmake ..
make
sudo make install
cmake -DPYTHON_CMD=python3 ..
pushd ../src/python/
make
sudo make install
popd
cd bcc
make install
Primero, aseguraos de que el kernel de destino tenga todo lo necesario...
cat /boot/config-$(uname -r) | grep 'CONFIG_BPF'
CONFIG_BPF=y
Si `CONFIG_BPF=y` está habilitado en vuestro sistema, estamos listos para continuar.
Lo que queremos lograr con este simple hello world o "Hola Mundo" es obtener visibilidad sobre cuándo IRIS realiza llamadas al sistema de Linux, sin utilizar nada más que las herramientas de eBPF y el propio kernel.
Aquí hay una buena manera de abordar la exploración:
1️⃣ Encontrad una llamada al sistema de Linux que os interese.
sudo ls /sys/kernel/debug/tracing/events/syscalls
Para este ejemplo, vamos a capturar cuando alguien (modificado para capturar IRIS) cree un directorio a través de la llamada al sistema `sys_enter_mkdir`.
2️⃣ Incorporadlo en el siguiente Hello World o "Hola Mundo":
El programa BPF que debéis cargar y ejecutar está en la variable `BPF_SOURCE_CODE`. Modificadlo para incluir la llamada al sistema que queréis capturar.
from bcc import BPF
from bcc.utils import printb
BPF_SOURCE_CODE = r"""
TRACEPOINT_PROBE(syscalls, sys_enter_mkdir) {
bpf_trace_printk("Directory was created by IRIS: %s\n", args->pathname);
return 0;
}
"""
bpf = BPF(text = BPF_SOURCE_CODE)
print("Go create a dir with IRIS...")
print("CTRL-C to exit")
while True:
try:
(task, pid, cpu, flags, ts, msg) = bpf.trace_fields()
if "iris" in task.decode("utf-8"):
printb(b"%s-%-6d %s" % (task, pid, msg))
except ValueError:
continue
except KeyboardInterrupt:
break
3️⃣ Cargadlo en el Kernel, activadlo
.png)
Cread un directorio en IRIS.
.png)
¡Inspeccionad el rastro!
.png)
Binarios potenciados por eBPF
No tarda mucho al explorar el repositorio de bcc y darse cuenta de que hay muchos ejemplos, herramientas y binarios que aprovechan eBPF para realizar trazas interesantes. En este caso, utilizar "grep" será suficiente para extraer algo de valor.
Hagamos exactamente eso en el inicio y parada de IRIS con algunos ejemplos proporcionados
`execsnoop` traza nuevos procesos a través de las llamadas al sistema `exec()`.
Este aquí cuenta la historia de los argumentos que se pasan a `irisdb` al iniciar y detener.
sudo python3 execsnoopy.py | grep iris
iris 3014275 COMM PID PPID RET ARGS
3011645 0 /usr/bin/iris stop IRIS quietly restart
irisstop 3014275 3011645 0 /usr/irissys/bin/irisstop quietly restart
irisdb 3014276 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
irisdb 3014277 3014275 0 ./irisdb -s/data/IRIS/mgr/ -U -B OPT^SHUTDOWN(1)
irisdb 3014279 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
irisdb 3014280 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
sh 3014281 3014275 0 /bin/sh -c -- /usr/irissys/bin/irisdb -s /data/IRIS/mgr/ -cL
irisdb 3014282 3014281 0 /usr/irissys/bin/irisdb -s /data/IRIS/mgr/ -cL
irisdb 3014283 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
irisrecov 3014284 3014275 0 ./irisrecov /data/IRIS/mgr/ quietly
iriswdimj 3014678 3014284 0 /usr/irissys/bin/iriswdimj -t
iriswdimj 3014679 3014284 0 /usr/irissys/bin/iriswdimj -j /data/IRIS/mgr/
rm 3014680 3014284 0 /usr/bin/rm -f iris.use
irisdb 3014684 3014275 0 ./irisdb -s/data/IRIS/mgr/ -w/data/IRIS/mgr/ -cd -B -V CLONE^STU
sh 3014685 3014275 0 /bin/sh -c -- /usr/irissys/bin/irisdb -s /data/IRIS/mgr/ -cL
irisdb 3014686 3014685 0 /usr/irissys/bin/irisdb -s /data/IRIS/mgr/ -cL
irisdb 3014687 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
irisrecov 3014688 3014275 0 ./irisrecov /data/IRIS/mgr/ quietly
iriswdimj 3015082 3014688 0 /usr/irissys/bin/iriswdimj -t
iriswdimj 3015083 3014688 0 /usr/irissys/bin/iriswdimj -j /data/IRIS/mgr/
rm 3015084 3014688 0 /usr/bin/rm -f iris.use
irisdb 3015088 3014275 0 ./irisdb -s/data/IRIS/mgr/ -w/data/IRIS/mgr/ -cc -B -C/data/IRIS/iris.cpf*IRIS
irisdb 3015140 3014275 0 ./irisdb -s/data/IRIS/mgr/ -w/data/IRIS/mgr/ -U -B -b1024 -Erunlevel=sys/complete QUIET^STU
irisdb 3015142 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 START^MONITOR
irisdb 3015143 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 START^CLNDMN
irisdb 3015144 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 ErrorPurge^Config.Startup
irisdb 3015145 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 START^LMFMON
irisdb 3015146 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 ^RECEIVE
irisdb 3015147 3015146 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p16 SCAN^JRNZIP
irisdb 3015148 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 OneServerJob^STU
irisdb 3015149 3015148 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p19 Master^%SYS.SERVER
irisdb 3015150 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 systemRestart^%SYS.cspServer2
irisdb 3015151 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 SERVERS^STU1
requirements_ch 3015152 3015140 0 /usr/irissys/bin/requirements_check
dirname 3015153 3015152 0 /usr/bin/dirname /usr/irissys/bin/requirements_check
httpd 3015215 3015151 0 /usr/irissys/httpd/bin/httpd -f /data/IRIS/httpd/conf/httpd.conf -d /usr/irissys/httpd -c Listen 52773
irisdb 3015362 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 OnSystemStartup^HS.FHIRServer.Util.SystemStartup
irisdb 3015363 3015140 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p13 OnSystemStartup^HS.HC.Util.SystemStartup
irisdb 3015364 3015151 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p21 RunManager^%SYS.Task
irisdb 3015365 3015151 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p21 Start^%SYS.Monitor.Control
irisdb 3015366 3015151 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p21 Daemon^LOGDMN
irisdb 3015367 3015151 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p21 RunDaemon^%SYS.WorkQueueMgr
irisdb 3015368 3015151 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p21 RunRemoteQueueDaemon^%SYS.WorkQueueMgr
irisdb 3015369 3015362 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p19 RunAll^HS.HC.Util.Installer.Upgrade.BackgroundItem
irisdb 3015370 3014275 0 ./irisdb -s/data/IRIS/mgr/ -cV
irisdb 3015436 3015367 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p25 startWork^%SYS.WorkQueueMgr
irisdb 3015437 3015367 0 /usr/irissys/bin/irisdb -s/data/IRIS/mgr -cj -p25 startWork^%SYS.WorkQueueMgr
`statsnoop` traza llamadas al sistema `stat()`, devolviendo atributos de archivos sobre un inodo y el acceso a archivos/directorios.
Este aquí es informativo para el acceso a nivel de directorio y archivo durante el inicio/parada. Es un poco ruidoso, pero ofrece información sobre lo que IRIS está haciendo durante el arranque, incluyendo el acceso a CPF, diarios, actividad de WIJ y el uso de herramientas del sistema para completar el trabajo.
sudo python3 statsnoop.py | grep iris
3016831 irisdb 0 0 /data/IRIS/mgr/
3016831 irisdb 0 0 /data/IRIS/mgr/
3016825 irisstop 0 0 /data/IRIS/mgr
3016825 irisstop 0 0 /usr/irissys/bin/irisuxsusr
3016825 irisstop 0 0 ./irisdb
3016825 irisstop 0 0 ../bin
3016832 sh -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v3/
3016832 sh -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v2/
3016832 sh 0 0 /usr/irissys/bin/
3016832 sh 0 0 /home/irisowner
3016833 irisdb -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v3/
3016833 irisdb -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v2/
3016833 irisdb 0 0 /usr/irissys/bin/
3016833 irisdb 0 0 /data/IRIS/mgr/
3016833 irisdb 0 0 /data/IRIS/mgr/
3016833 irisdb 0 0 /data/IRIS/mgr/
3016834 irisstop 0 0 ./irisdb
3016834 irisstop 0 0 ../bin
3016834 irisdb -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v3/
3016834 irisdb -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v2/
3016834 irisdb 0 0 /usr/irissys/bin/
3016834 irisdb 0 0 /data/IRIS/mgr/
3016834 irisdb 0 0 /data/IRIS/mgr/
3016835 irisstop 0 0 ./irisrecov
3016835 irisstop 0 0 ../bin
3016835 irisrecov -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v3/
3016835 irisrecov -1 2 /usr/irissys/bin/glibc-hwcaps/x86-64-v2/
3016835 irisrecov 0 0 /usr/irissys/bin/
3016835 irisrecov 0 0 /home/irisowner
3016835 irisrecov 0 0 .
3016835 irisrecov 0 0 iris.cpf
3016841 irisrecov 0 0 /usr/bin/cut
3016841 irisrecov 0 0 /usr/bin/tr
3016841 irisrecov 0 0 /usr/bin/sed
3017761 requirements_ch 0 0 /home/irisowner
3017761 requirements_ch -1 2 /usr/irissys/bin/requirements.isc
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb 0 0 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf_5275
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf_5275
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf_5275
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /usr/lib64/libcrypto.so.1.1
3017691 irisdb -1 2 /usr/lib64/libcrypto.so.3
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/iris.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf_20240908
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/_LastGood_.cpf_5275
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/_LastGood_.cpf_5275
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb -1 2 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /etc/localtime
3017691 irisdb 0 0 /data/IRIS/_LastGood_.cpf
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017691 irisdb 0 0 /data/IRIS/mgr/irisaudit/
3017756 irisdb -1 2 /data/IRIS/mgr/journal/20240908.002
3017756 irisdb -1 2 /data/IRIS/mgr/journal/20240908.002
3017756 irisdb 0 0 /data/IRIS/mgr/journal/20240908.002z
3017756 irisdb -1 2 /data/IRIS/mgr/journal/20240908.002
3017756 irisdb 0 0 /data/IRIS/mgr/journal/20240908.002z
3017756 irisdb -1 2 /data/IRIS/mgr/journal/20240908.001
Flamegraphs

Una de las cosas más interesantes que encontré con las herramientas de eBPF fue la implementación de flamegraphs de Brendan Gregg sobre la salida de bpf para entender el rendimiento y los rastros de pila.
Dado el siguiente registro de perf durante el inicio/parada de IRIS:
sudo perf record -F 99 -a -g -- sleep 60
[ perf record: Woken up 7 times to write data ]
[ perf record: Captured and wrote 3.701 MB perf.data (15013 samples) ]
Generad el siguiente flamegraph con lo siguiente:
sudo perf script > out.perf
./stackcollapse-perf.pl out.perf > /tmp/gar.thing
./flamegraph.pl /tmp/gar.thing > flamegraph.svg
.png)
Intenté subir el SVG, pero no funcionó con este editor y, por alguna razón, no pude adjuntarlo. Entended, sin embargo, que es interactivo y se puede hacer clic para profundizar en los rastros de pila, además de simplemente verse bien.
- La función en la parte inferior es la función en el CPU. Cuanto más arriba en el eje y, más anidada está la función.
- El ancho de cada función en el gráfico representa el tiempo que esa función tardó en ejecutarse como un porcentaje del tiempo total de su función principal.
- Encontrar funciones que estén tanto altas en el eje y (profundamente anidadas) como anchas en el eje x (intensivas en tiempo) es una excelente manera de identificar problemas de rendimiento y optimización.
"alto y ancho" <--- 👀
red == user-level
orange == kernel
yellow == c++
green == JIT, java etc.
Me gustó mucho esta explicación sobre la interpretación de flamegraphs que se presenta aquí (crédito a la explicación anterior), de donde obtuve una comprensión básica sobre cómo leer *flamegraphs*. Es especialmente potente para aquellos que ejecutan Python en IRIS en producciones con código en el espacio de usuario y buscan optimización.
Avanzando y mejorando, espero que esto haya despertado vuestro interés. Ahora, pasemos al mundo de las aplicaciones eBPF, donde los expertos han desarrollado soluciones fenomenales para poner eBPF a trabajar en flotas de sistemas de manera segura y ligera.