乐趣区

关于开源:基于eBPF技术的开源项目Kindling之探针架构介绍

Kindling 开源我的项目是一款基于 eBPF 技术的云原生可观测性我的项目。本文将次要介绍探针的具体架构设计。

Kindling 探针的架构设计理念

Kindling 架构设计中有一个很重要的理念:关注点拆散 (Separation of Concerns)。eBPF 技术或者内核模块是一种内核技术,须要的背景常识是 C 语言和操作系统常识。而可观测开发者关注的是要输入什么样的指标,同时因为平时应用 Go、Java 这一类语言较多,对 C 也比拟陌生,所以咱们的设计是基于两层的分层畛域。上层是 eBPF 的开发能力,次要是为事件透出服务;下层是可观测性需求开发,次要是为数据分析和指标产生服务,同时能够不便扩大可观测场景化需要。

另外一个重要的理念是:不反复造轮子 ,咱们指标是把 eBPF 的能力以简略的形式透出给用户应用。所以 kindling 的设计是以 falcosecurity-libs 为根底的。目前这个开源我的项目承当的主要职责就是零碎调用的事件透出,对于可观测方面的能力须要进一步扩大。然而它有一个劣势是它会将原始内核数据和 cgroup 信息进行关联,不便后续将数据关联到 k8s 相干的 resources, 同时 falcosecurity-libs 也对原始数据做了预处理,比方将网络数据进行更丰盛的关联,让用户可能间接拿到某个对 fd 操作的网络事件属于哪个四元组的信息,所以咱们复用了这部分能力。但 falcosecurity-libs 自身并不反对 kprobe、uprobe 等能力,kindling 目前曾经对其扩大了 kprobe 能力,后续也会继续一直的扩大 uprobe 等能力,同时还会集成其余开源工具的数据能力。
一般来说,eBPF 探针次要由两局部程序组成:内核态程序用作采集数据以及用户态程序用作剖析数据。但基于以上两个理念,咱们的架构并不是传统的两局部。咱们基于关注点拆散理念,为了让 cloud-native 畛域的开发者可能更不便的应用 eBPF 的能力,把原来 falcosecurity-libs 的 C /C++ 用户态程序拆分成了一个 Go 程序和一个 C /C++ 程序,让用户能更关注本人善于的畛域。

Kindling 探针架构介绍

Kindling 探针整体蕴含三个局部:用户态 Go 程序、用户态 C /C++ 程序和内核态 drivers 程序。用户态 Go 程序满足的是下层可观测需要的开发,其余两个局部实现的是内核需要的开发。这样不同畛域的人能够用本人善于的语言开发本人关注的内容,同时探针也有较好的松耦合个性。Kindling 具体组件形容如下:

内核态程序:drivers

为了更好的反对低版本内核的可观测能力,kindling 的探针应用内核模块的模式反对低版本内核,所以 drivers 又分为 eBPF probe 以及内核模块。drivers 次要负责采集内核事件,将事件放入由间接内存映射技术创立的数据结构,供用户态程序获取并解决。在事件采集这一层后续会继续将其余开源工具集成进来,比方 BCC、bpftrace。

用户态 C /C++ 程序:kindling-probe

kindling-probe 是一个由 C /C++ 语言编写的程序,运行时以一个独自的 container 运行在 pod 中,其次要的职责是负责和内核态程序进行交互并将内核事件裸露给下层处理程序。目前负责的工作次要有三个局部:

  • 负责调用 bpf API 加载 eBPF 内核态的字节码或者装置低版本内核的内核模块
  • 负责从 mmap 映射进去的 ringbuffer 构造中读取内核产生的原始事件并对原始事件进行预处理,最初转换为规范事件格局发送给 kindling-collector
  • 负责提供动静配置通道,例如能够通过配置实现内核数据过滤,缩小原始数据量以及无关数据

用户态 Go 程序:kindling-collector

用户态 Go 程序是一个可扩大模块,用户能够订阅本人关注的内核事件,基于本人的应用场景扩大本人的分析程序。目前 kindling 实现的分析程序被称为 kindling-collector,它在运行时也是以一个独自的 container 运行在 pod 中,其主要职责是负责获取事件并进行剖析,并对数据进行 label 的丰盛。kindling-collector 局部模块集成了 opentelemetry 的 SDK,这样 kindling 的指标在输入时有较高的灵活性,能够输入到 opentelemetry collector、prometheus、kindling 标准版后端等多种可观测性平台。目前 kindling-collector 订阅的事件只是 probe 裸露进去的局部事件,次要是以零碎调用以及 kprobe 为主,具体订阅信息如下:
subscribe:

    - name: syscall_exit-writev
      category: net
    - name: syscall_exit-readv
      category: net
    - name: syscall_exit-write
      category: net
    - name: syscall_exit-read
      category: net
    - name: syscall_exit-sendto
      category: net
    - name: syscall_exit-recvfrom
      category: net
    - name: syscall_exit-sendmsg
      category: net
    - name: syscall_exit-recvmsg
      category: net
    - name: kprobe-tcp_close
    - name: kprobe-tcp_rcv_established
    - name: kprobe-tcp_drop
    - name: kprobe-tcp_retransmit_skb

程序间通信形式

drivers 和 kindling-probe 程序之间通信形式

eBPF 程序采纳 BPF MAP 数据结构通信;内核模块采纳 mmap 结构的 ringbuffer 进行通信。下图是 eBPF 程序应用的架构模型,为了兼容 4.X 内核,BPFMAP 构造应用的是 BPF_MAP_TYPE_PERF_EVENT_ARRAY,每个 cpu 都有相应的一个 perf-event 的 map,在 kindling-probe 层会对事件进行排序组合。

kindling-probe 和 kindling-collector 之间通信形式

这个过程应用了 unix domain socket,它是一种 IPC 形式,尽管应用了 socket,然而因为数据不须要通过网络协议栈,所以有比拟好的传输性能。目前 probe 裸露的 kindling event 会进行序列化发送给 unix domain socket,collector 会从 socket 中读取数据并进行反序列化,而后失去标准化事件进行剖析。

Kindling 通信标准化事件格局

正如不同微服务间的通信大多都基于一份 RESTful 的 HTTP 接口定义,kindling 在分层后也须要一种标准化的事件格局来屏蔽不同畛域的实现细节,目前 kindling 设计的事件格局被称为 kindling-event。Kindling-event 是 kindling-probe 程序裸露进去的内核事件,底层 eBPF 程序会遵循 kindling-event 的规范格局裸露数据,这样下层利用也能基于规范去剖析事件。具体的 kindling event 的构造如下:
message KindlingEvent {
Source source = 1;
// Timestamp in nanoseconds at which the event were collected.
uint64 timestamp = 2;
// Name of Kindling Event
string name = 3;
// Category of Kindling Event, enum
Category category = 4;
// Native attributes of hook point, including arguments or return value.
Property Native_attributes = 5;
// User-defined Attributions of Kindling Event, now including latency for syscall.
repeated KeyValue user_attributes = 6;
// Context includes Thread information and Fd information.
Context ctx = 7;
}

对 Kindling 感兴趣或者在云可观测性方面有问题的小伙伴欢送与咱们分割:

分割咱们

关注咱们

退出移动版