Grafana Beyla
测试环境
Ubuntu 20.04 LTS内核版本不满足要求,Beyla要求至少5.8以上
Static hostname: test
Icon name: computer-vm
Chassis: vm
Machine ID: 22349ac6f9ba406293d0541bcba7c05d
Boot ID: 83bb7e5dbf27453c94ff9f1fe88d5f02
Virtualization: vmware
Operating System: Ubuntu 22.04.4 LTS
Kernel: Linux 5.15.0-105-generic
Architecture: x86-64
Hardware Vendor: VMware, Inc.
Hardware Model: VMware Virtual Platform
了解Grafana Beyla
Grafana Beyla 是一个基于 eBPF(Extended Berkeley Packet Filter)的应用程序自动仪表化工具,旨在轻松实现应用程序的可观测性。它使用 eBPF 自动检查应用程序可执行文件和操作系统网络层,并捕获与 Web 事务相关的跟踪跨度和 Linux HTTP/S 和 gRPC 服务的 Rate Errors Duration (RED) 指标,而无需对应用程序代码或配置进行任何修改.
以下是 Grafana Beyla 的一些特点:
- 自动仪表化各种编程语言编写的应用程序,例如 Go、C/C++、Rust、Python、Ruby、Java(包括 GraalVM Native)、NodeJS、.NET 等。
- 高效的仪表化和低开销的数据捕获,适用于原生编译的代码,甚至适用于解释性语言。
- 以 OpenTelemetry 格式和原生 Prometheus 指标的形式导出数据。
- 为 Go 服务提供分布式跟踪。
Grafana Beyla 的开发目前处于早期阶段。它是一个基于 eBPF 的应用程序自动仪表化工具,旨在轻松实现应用程序的可观测性。Beyla 使用 eBPF 自动检查应用程序可执行文件和操作系统网络层,并捕获与 Web 事务相关的跟踪跨度和 Linux HTTP/S 和 gRPC 服务的 Rate Errors Duration (RED) 指标,而无需对应用程序代码或配置进行任何修改。
beyla支持通过eBPF,无侵入地自动采集应用程序的trace信息。以下是Beyla对trace的采集实现原理,以golang的net/http为例:
-
整体原理:
- Beyla监听了golang应用程序的
net/http
中的函数:net/http.serverHandler.ServeHTTP
net/http.(*Transport).roundTrip
- 监听
ServeHTTP
时:- 若请求中没有trace信息,则生成
traceparent
,存入go_trace_map
结构(key=goroutine地址,value=trace信息)。 - 若请求中有trace信息,则根据trace信息,重新生成span,存入
go_trace_map
结构。
- 若请求中没有trace信息,则生成
- 监听
roundTrip
的调用:- 首先,根据goroutine地址,读取
go_trace_map
结构,得到trace信息。 - 然后,将当前连接的trace信息,存入
ongoing_http_client_requests
结构(key=goroutine地址,value=trace信息)。
- 首先,根据goroutine地址,读取
- 监听
roundTrip
的调用返回:- 首先,根据goroutine地址,读取
ongoing_http_client_requests
结构,得到trace信息。 - 然后,将当前调用的trace信息,转换为
http_request_trace
结构,保存到ringbuf中。 - 最终,eBPF用户程序从ringbuf中读取trace信息,完成采集。
- 首先,根据goroutine地址,读取
- Beyla监听了golang应用程序的
-
监听uprobe/ServeHTTP处理流程:
- 首先,提取goroutine和request指针。
- 然后,通过
server_trace_parent()
函数,处理trace信息,存入go_trace_map
结构。 - 最后,将数据存入
ongoing_http_server_requests
结构。
-
监听uprobe/roundTrip处理流程:
- 首先,提取goroutine地址和request地址。
- 然后,根据goroutine地址和request,查找trace信息。
-
traceparent格式:
- traceparent的格式为:
00-traceId-parentId-type
。 - 一个http调用:
- 产生了一个trace信息,traceId为
9201c25ae90fee19c5bb224e5b1d4941
。 - 产生了两个span信息:
- span2的parentSpanId为
0000000000000000
,是用户发起的http调用的span。 - span1的parentSpanId为
4228643b4d469989
,即发起www.baidu.com
调用的span。
- span2的parentSpanId为
- 产生了一个trace信息,traceId为
- traceparent的格式为:
Beyla不仅采集了trace信息,还实现了trace context propagation,使得外部服务可以根据header中的traceparent字段了解trace上下文信息。
requirements
- 1、linux内核版本高于5.8,5.14之后的版本默认开启BPF。有/sys/kernel/btf/vmlinux的系统是开启BPF的。
- 2、开启eBPF。
- 3、如果要检测go应用,必须是go1.17版本以上编译的。
- 4、执行Beyla的管理权限。
检查eBPF支持
如果输出包含CONFIG_BPF=y,则表示eBPF已经启用。
# grep CONFIG_BPF /boot/config-$(uname -r)
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
CONFIG_BPFILTER=y
CONFIG_BPFILTER_UMH=m
CONFIG_BPF_JIT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_BPF_EVENTS=y
CONFIG_BPF_KPROBE_OVERRIDE=y
启用未授权的eBPF
允许非特权用户使用eBPF功能
# sysctl kernel.unprivileged_bpf_disabled
kernel.unprivileged_bpf_disabled = 2
# sysctl -w kernel.unprivileged_bpf_disabled=0
安装必要工具
apt install -y bpfcc-tools linux-headers-$(uname -r)
安装使用
设置go
# 下载go1.22.2.linux-amd64.tar.gz
wget https://go.dev/dl/go1.22.2.linux-amd64.tar.gz
# 设置代理
/root/go/bin/go env -w GO111MODULE=on
/root/go/bin/go env -w GOPROXY=https://goproxy.cn
安装beyla
/root/go/bin/go install github.com/grafana/beyla/cmd/beyla@latest
运行beyla
配置文件方式
cat > config.yml <<EOF
open_port: 443
prometheus_export:
port: 8999
EOF
/root/go/bin/beyla -config config.yml
命令行方式
BEYLA_PROMETHEUS_PORT=8999 BEYLA_OPEN_PORT=443 BEYLA_PRINT_TRACES=true /root/go/bin/beyla
trace应用程序生成grafana监控
安装grafana
apt-get install -y adduser libfontconfig1 musl
wget https://dl.grafana.com/oss/release/grafana_10.4.2_amd64.deb
dpkg -i grafana_10.4.2_amd64.deb
systemctl start grafana-server
systemctl enable grafana-server
编写三个golang互相调用应用示例
server1
package main
import (
"io/ioutil"
"log"
"net/http"
"time"
)
func main() {
// Define HTTP handler for service1
http.HandleFunc(