菜单
开源

pyroscope.ebpf

pyroscope.ebpf 为当前主机配置 eBPF 分析任务。收集的性能分析结果将转发到 forward_to 中提供的接收者列表。

注意

要使用 pyroscope.ebpf 组件,必须以 root 身份运行 Alloy 并在进程 ID 命名空间内运行。

您可以通过提供不同的标签来指定多个 pyroscope.ebpf 组件,但这不是推荐的,因为它可能会导致额外的内存和 CPU 使用。

支持的语言

此 eBPF 分析器只能收集 CPU 分析结果。通常,支持原生日编译语言如 C/C++、Go 和 Rust。有关其他要求的更多信息,请参阅 未知符号故障排除

Python 是唯一受支持的高级语言,只要 python_enabled=true。其他高级语言如 Java、Ruby、PHP 和 JavaScript 需要额外的配置以正确显示这些语言中方法的堆栈跟踪。目前,这些语言的 CPU 使用率报告为属于运行时方法。

用法

alloy
pyroscope.ebpf "LABEL" {
  targets    = TARGET_LIST
  forward_to = RECEIVER_LIST
}

参数

该组件会配置并启动一个新 eBPF 分析任务,从当前主机收集性能分析结果。

您可以使用以下参数来配置 pyroscope.ebpf。只有 forward_totargets 字段是必需的。省略的字段将采用默认值。

名称类型描述默认值必需
targetslist(map(string))按容器 ID 分组的分析目标列表yes
forward_tolist(ProfilesReceiver)收集到后发送到接收者列表yes
collect_intervalduration收集分析结果的频率15sno
sample_rateint每秒收集分析样本的次数97no
pid_cache_sizeintpid -> proc 符号表 LRU 缓存的大小32no
build_id_cache_sizeintelf 文件 build id -> 符号表 LRU 缓存的大小64no
same_file_cache_sizeintelf 文件 -> 符号表 LRU 缓存的大小8no
container_id_cache_sizeintpid -> 容器 ID 表 LRU 缓存的大小1024no
collect_user_profilebool启用/禁用用户空间分析收集的标志trueno
collect_kernel_profilebool启用/禁用内核空间分析收集的标志trueno
demanglestringC++ 冲突消除模式。可用选项为:`none`,`simplified`,`templates`,`full`noneno
python_enabledbool启用/禁用 Python 分析的标志trueno
symbols_map_sizeinteBPF 符号表的大小16384no
pid_map_sizeinteBPF PID 表的大小2048no

导出字段

pyroscope.ebpf 不导出其他组件可以引用的字段。

组件健康

pyroscope.ebpf 只有在给定无效配置时才报告为不健康。

调试信息

  • targets 当前跟踪的活跃目标。
  • pid_cache 每个进程的 ELF 符号表及其符号计数。
  • elf_cache 每个构建 ID 及相同文件的符号表及其符号计数。

调试指标

  • pyroscope_fanout_latency(直方图):向直接和间接组件发送的写入延迟。
  • pyroscope_ebpf_active_targets(仪表盘):组件跟踪的活跃目标数量。
  • pyroscope_ebpf_profiling_sessions_total(计数器):完成的概要分析会话数量。
  • pyroscope_ebpf_profiling_sessions_failing_total(计数器):失败的概要分析会话数量。
  • pyroscope_ebpf_pprofs_total(计数器):eBPF 组件收集的 pprof 分析数量。

概要收集行为

pyroscope.ebpf 组件收集当前主机上运行的进程关联的堆栈跟踪。您可以使用 sample_rate 参数定义每秒收集的堆栈跟踪数量。默认值为 97。

如果您未定义以下标签,则会自动将其注入收集的概要中。这些标签可以帮助您定位分析目标。

标签描述
service_namePyroscope 服务名称。如果可能,它将自动从发现元标签中选择。否则,默认为 unspecified
__name__pyroscope 指标名称。默认为 process_cpu
__container_id__从目标派生的容器 ID。

目标

targets 的每个目标必须包含以下特殊标签之一 必须,并且标签必须与被分析的容器或进程相对应

  • __container_id__:容器 ID。
  • __meta_docker_container_id:Docker 容器的 ID。
  • __meta_kubernetes_pod_container_id:Kubernetes pod 容器的 ID。
  • __process_pid__:进程 ID。

然后,每个进程都与目标列表中的指定目标相关联,该目标通过容器 ID 或进程 PID 确定。

如果进程的容器 ID 与目标的容器 ID 标签相匹配,则根据容器 ID 对堆栈跟踪进行聚合。如果进程的 PID 与目标的进程 PID 标签相匹配,则根据进程 PID 对堆栈跟踪进行聚合。否则,该进程不进行分析。

服务名称

特殊标签 service_name 是必需的,并且始终必须存在。如果没有指定,则尝试从多个来源推断。

  • __meta_kubernetes_pod_annotation_pyroscope_io_service_name,它是一个 pyroscope.io/service_name pod 注解。
  • __meta_kubernetes_namespace__meta_kubernetes_pod_container_name
  • __meta_docker_container_name

如果 service_name 未指定且无法推断,则将其设置为 unspecified

处理未知符号

符号从各种来源提取,包括

  • ELF 文件中的 .symtab.dynsym 部分。
  • 调试 ELF 文件中的 .symtab.dynsym 部分。
  • Go 语言 ELF 文件中的 .gopclntab 部分。

调试文件的搜索遵循 gdb 算法。例如,如果分析器希望找到带有 .gnu_debuglink 设置为 libc.so.6.debug 和构建 ID 0123456789abcdef/lib/x86_64-linux-gnu/libc.so.6 的调试文件。将检查以下路径

  • /usr/lib/debug/.build-id/01/0123456789abcdef.debug
  • /lib/x86_64-linux-gnu/libc.so.6.debug
  • /lib/x86_64-linux-gnu/.debug/libc.so.6.debug
  • /usr/lib/debug/lib/x86_64-linux-gnu/libc.so.6.debug

处理未知符号

您收集的概要中的未知符号表示分析器无法访问与跟踪中的给定地址关联的 ELF 文件。

这可能是以下几种原因造成的

  • 进程已终止,导致 ELF 文件不可访问。
  • ELF 文件已损坏或未识别为 ELF 文件。
  • /proc/pid/maps 中没有与堆栈跟踪中的地址对应的 ELF 文件条目。

解决未解析的符号

如果您只看到模块名称(例如,/lib/x86_64-linux-gnu/libc.so.6),而没有对应的函数名称,这表明符号无法映射到相应的函数名称。

这可能是以下几种原因造成的

  • 二进制文件已经被剥离,ELF 文件中没有 .symtab、.dynsym 或 .gopclntab 部分。
  • 调试文件丢失或无法定位。

为了修复您的二进制文件,请确保它们没有被剥离,或者您有可用的单独调试文件。您可以通过运行以下命令实现

bash
objcopy --only-keep-debug elf elf.debug
strip elf -o elf.stripped
objcopy --add-gnu-debuglink=elf.debug elf.stripped elf.debuglink

对于系统库,确保已安装调试符号。以 Ubuntu 为例,您可以通过执行以下命令安装 libc 的调试符号

bash
apt install libc6-dbg

理解平坦的堆栈跟踪

如果您的配置文件显示许多浅层堆栈跟踪,通常是1-2层,这意味着您的二进制可能是在没有帧指针的情况下编译的。

要使用帧指针编译您的代码,请在编译器选项中包含 -fno-omit-frame-pointer 标志。

示例

Kubernetes 发现

在以下示例中,使用 discovery.kubernetes 发现同一节点上的 pod,收集性能配置文件。Pod 选择依赖于 HOSTNAME 环境变量,如果使用 Alloy Helm 图表,则是 pod 名称。设置 service_name 标签为从 Kubernetes 元标签中的 {__meta_kubernetes_namespace}/{__meta_kubernetes_pod_container_name}

alloy
discovery.kubernetes "all_pods" {
  role = "pod"
  selectors {
    field = "spec.nodeName=" + env("HOSTNAME")
    role = "pod"
  }
}

discovery.relabel "local_pods" {
  targets = discovery.kubernetes.all_pods.targets
  rule {
    action = "drop"
    regex = "Succeeded|Failed"
    source_labels = ["__meta_kubernetes_pod_phase"]
  }
  rule {
    action = "replace"
    regex = "(.*)@(.*)"
    replacement = "ebpf/${1}/${2}"
    separator = "@"
    source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
    target_label = "service_name"
  }
  rule {
    action = "labelmap"
    regex = "__meta_kubernetes_pod_label_(.+)"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_namespace"]
    target_label = "namespace"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_pod_name"]
    target_label = "pod"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_node_name"]
    target_label = "node"
  }
  rule {
    action = "replace"
    source_labels = ["__meta_kubernetes_pod_container_name"]
    target_label = "container"
  }
}
pyroscope.ebpf "local_pods" {
  forward_to = [ pyroscope.write.endpoint.receiver ]
  targets = discovery.relabel.local_pods.output
}

pyroscope.write "endpoint" {
  endpoint {
    url = "http://pyroscope:4040"
  }
}

Docker 发现

在以下示例中,从 discovery.docker 查找的容器中收集性能配置文件,并忽略来自任何 Docker 容器外部的所有其他配置文件。设置 service_name 标签为 __meta_docker_container_name 标签。

alloy
discovery.docker "linux" {
  host = "unix:///var/run/docker.sock"
}

discovery.relabel "local_containers" {
  targets = discovery.docker.linux.targets
  rule {
    action = "replace"
    source_labels = ["__meta_docker_container_name"]
    target_label = "service_name"
  }
}

pyroscope.write "staging" {
  endpoint {
    url = "http://pyroscope:4040"
  }
}

pyroscope.ebpf "default" {
  forward_to   = [ pyroscope.write.staging.receiver ]
  targets      = discovery.relabel.local_containers.output
}

兼容组件

pyroscope.ebpf 可以接受以下组件的参数

注意

某些组件之间的连接可能不合理,或可能需要进一步配置以正确连接。请参阅链接的文档以获取更多详细信息。