可观测性是一种理解和解释利用以后状态的能力,也是一种晓得何时呈现问题的办法。随着在 Kubernetes 和 OpenShift 上以微服务模式进行云部署的应用程序越来越多,可察看性受到了宽泛关注。许多应用程序都有严格的承诺,比方在停机工夫、提早和吞吐量方面的 SLA,因而网络层面的可观测性是一项十分必要的性能。网络层面的可观测性由不同的编排器提供,有的是内置反对,有的是通过插件和 operator 提供。
最近,eBPF(扩大的伯克利数据包过滤器)因其性能和灵活性成为在终端主机内核实现可察看性的热门抉择。通过这种办法,能够在网络数据门路的某些点(如套接字、TC 和 XDP)上挂接自定义程序。目前已公布了多个基于 eBPF 的开源插件和 operator,每个插件和 operator 都可插入终端主机节点,通过云上的编排器提供网络可察看性。
现有的可观测性工具
可观测性模块的外围局部是如何以非侵入形式收集必要数据。为此,应用代码埋点统计,咱们钻研了 eBPF 如何影响指标被观测模块的性能。测量方法和工具是开源的,你能够在咱们的 Git 仓库 中找到。在设计可扩大的高性能 eBPF 监控数据门路时,咱们还能为您提供一些有用的见解。
以下是现有的开源工具,可用于在网络和主机的上下文中实现可察看性:
Skydive
Skydive 是一款网络拓扑和流量分析器。它将探针下放到节点,以收集流量级信息。应用 PCAP、AF_Packet、Open vSwitch 等形式连贯探针。Skydive 应用 eBPF 捕捉流量指标,而不是捕捉整个数据包。连贯到套接字 Hook 点的 eBPF 实现应用哈希映射来存储流量头和指标(数据包、字节和方向)。
libebpfflow
Libebpfflow 是一个应用 eBPF 提供网络可见性的网络库。它 Hook 主机堆栈中的多个点,如 kernel probes(inet_csk_accept、tcp_retransmit_skb)和 tracepoints(net:netif_receive_skb、net:net_dev_queue),以剖析 TCP/UDP 流量状态、RTT 等。此外,它还为所剖析的流量提供过程和容器映射。其 eBPF 实现应用 perf event buffer 将 TCP 状态变动事件告诉用户空间。对于 UDP,它连贯到网络设备队列的跟踪点,并联合应用 LRU 哈希映射和 perf event buffer 来存储 UDP 流量指标。
eBPF Exporter
Cloudflare 的 eBPF Exporter 提供了用于插入自定义 eBPF 代码的 API,以记录感兴趣的自定义指标。它须要将整个 eBPF C 代码(以及挂钩点)附加到 YAML 文件中以进行部署。
Pixie
Pixie 应用 bpftrace 来跟踪零碎调用。它应用 TCP/UDP 状态音讯来收集必要的信息,而后将其发送到 Pixie Edge Module (PEM)。在 PEM 中,依据检测到的协定解析数据并存储以供查问。
Inspektor
Inspektor 是用于 Kubernetes 集群调试的工具汇合。它有助于低级内核原语与 Kubernetes 资源的映射。它作为 daemonset 增加到集群的每个节点上,以应用 eBPF 收集 syscall 等事件的跟踪。这些事件被写入 perf 环形缓冲区。最初,当产生故障时(例如,Pod 解体时),环形缓冲区会被追溯耗费。
L3AF
L3AF 提供了一组 eBPF 包,可应用 tail-calls 将其打包并串联起来。它提供了一个网络可察看性工具,可依据流标识将流量镜像到用户空间代理。此外,它还通过在 eBPF 数据门路中的 hash map 上存储流量记录,提供了一个 IPFIX 流量导出器。
Host-INT
Host-INT 扩大了带内网络遥测反对,以反对主机网络堆栈的遥测。从根本上说,INT 将每个数据包产生的切换提早嵌入到数据包的 INT 标头中。Host-INT 对两个主机之间的主机网络堆栈执行雷同的操作。Host-INT 有两个数据门路组件:基于 eBPF 的源和接收器。源运行在发送方主机接口的 TC Hook 上,接收器运行在接管方主机接口的 XDP Hook 上。从源上来说,它应用 hash map 来存储流量统计信息。此外,它还增加了带有入口 / 进口端口、工夫戳等的 INT 标头。在接收器处,它应用 perf array 在每个数据包达到时将统计信息发送到接收器用户空间程序,并将数据包发送到内核。
Falco
Falco 是一个云原生运行时平安我的项目。它应用 eBPF 探测器监控零碎调用,并在运行时对其进行解析。Falco 可对应用特权容器进行特权拜访、读写内核文件夹、增加用户、更改明码等流动配置警报。Falco 包含一个用户空间程序(作为 CLI 工具)和一个基于 libscap 和 libsinsp 库的 falco 驱动程序,前者用于指定警报和获取解析后的零碎调用输入。对于零碎调用探测,falco 应用 eBPF ring buffers。
Cilium
Cilium 的可观测性是通过 eBPF 实现的。Hubble 是一个在集群的每个节点上运行 eBPF 钩子的平台。它有助于深刻理解互相通信的服务,从而构建服务依赖关系图。它还有助于第 7 层监控,例如剖析 HTTP 调用和 Kafka 主题,以及通过 TCP 重传率进行第 4 层监控等。
Tetragon
Tetragon 是 Cilium 中用于平安和可察看性的可扩大框架。Tetragon 的底层驱动程序是 eBPF,应用环形缓冲区存储数据,但在监控 eBPF 的同时,还利用 eBPF 执行逾越虚构文件系统(VFS)、命名空间、零碎调用等各种内核组件的策略。
Aquasecurity Tracee
Tracee 是一款事件跟踪工具,用于调试通过 eBPF 构建的行为模式。Tracee 在 tc、kprobes 等处有多个挂钩点,用于监控和跟踪网络流量。在 tc 钩子点,它应用环形缓冲区(perf)向用户空间提交数据包级事件。
从新扫视 Flow metric agent 的设计
尽管不同工具的动机和实现形式各不相同,但所有可观测性工具的独特外围局部是用于收集可观测性指标的数据结构。尽管不同的工具采纳不同的数据结构来收集指标,但目前还没有进行性能测量,以理解用于收集和存储可观测性指标的数据结构的影响。为了补救这一差距,咱们应用不同的数据结构施行模板 eBPF 程序,从主机流量中收集雷同的流量指标。咱们应用 eBPF 中的以下数据结构(称为 “ 地图 ”)来收集和存储指标:
- Ring Buffer
- Hash
- Per-CPU Hash
- Array
- Per-CPU Array
Ring Buffer
环形缓冲区是 eBPF 数据门路和用户空间之间的共享队列,其中 eBPF 数据门路是生产者,用户空间程序是消费者。它可用于向用户空间发送每个数据包的“明信片”,以汇总流量指标。尽管这种办法既简略又能提供精确的后果,但因为它按数据包发送“明信片”,用户空间程序始终处于忙碌的循环中,因而无奈扩大。
Hash and Per-CPU Hash map
(每 CPU)Hash map 可用于 eBPF 数据门路,通过对流标识(例如 5 元组:IP、端口、协定)进行散列来聚合每个流的指标,并在流实现 / 未激活时将聚合信息驱赶到用户空间。尽管这种办法克服了环形缓冲区的毛病,每个流而不是每个数据包只发送一次明信片,但它也有一些毛病。
首先,多个流量有可能被散列到同一个条目中,从而导致流量指标汇总不精确。其次,对于内核 eBPF 数据门路来说,散列映射的内存必然无限,因而可能会被耗尽。因而,用户空间程序必须执行驱赶逻辑,以便在超时时一直驱赶流量。
Array-based map
(每 CPU)基于数组的映射也可用于在逐出用户空间之前长期存储每数据包明信片,只管这不是一个显著的抉择。应用数组有一个劣势,即在数组中存储每个数据包的信息,直到数组已满,而后仅在数组已满时才刷新到用户空间。这样,与应用每个数据包的环形缓冲区相比,它能够改善用户空间的忙循环周期。另外,它不存在 Hash map 的哈希抵触问题。然而,实现起来很简单,因为当主数组将其内容刷新到用户空间时,须要多个冗余数组来存储每个数据包的明信片。
Measurements
到目前为止,咱们曾经钻研了可用于应用多种数据结构实现流度量收集的选项。当初是时候钻研每种形式的性能了。为此,咱们施行了代表性的 eBPF 程序来收集流量指标。为此,咱们施行了具备代表性的 eBPF 程序来收集流量指标。咱们应用的代码可在咱们的 Git 仓库 中找到。此外,咱们还在 PcapPlusPlus 的根底上定制了基于 UDP 的数据包生成器,通过发送流量进行测量。
该图形容了试验设置:
(Kannan/Naik/Lev-Ran, CC BY-SA 4.0)
察看代理是执行流度量收集的 eBPF 数据门路,挂接到发送方的 tc hook 点。咱们应用两台通过 40G 链路连贯的裸机服务器。数据包生成是应用 40 个独立的 core 实现的。为了正确看待这些测量后果,基于 libpcap 的 Tcpdump 可用于收集相似的流量信息。
Single Flow
咱们最后应用单流 UDP 帧运行测试。单流测试能够向咱们展现察看代理能够容忍的单流流量突发量。如下图所示,没有任何察看代理的本机性能约为 4.7 Mpps(每秒百万数据包),而运行 tcpdump 时,吞吐量降至约 2 Mpps。应用 eBPF,咱们察看到性能从 1.6 Mpps 到 4.7 Mpps 不等,具体取决于用于存储流指标的数据结构。应用 HashMap 等共享数据结构,咱们察看到单流性能降落最显着,因为每个数据包都会写入映射中的雷同条目,而不论其源自哪个 CPU。
对于单个流突发,Ringbuffer 的性能比单个 HashMap 稍好。应用每 CPU 哈希映射,咱们察看到吞吐量性能显着进步,因为来自多个 CPU 的数据包不再争用雷同的映射条目。然而,在没有任何察看代理的状况下,性能依然是本机性能的一半。(请留神,此性能未解决哈希抵触和驱赶。)
应用(每个 CPU)阵列,咱们看到单个流的吞吐量显着减少。咱们能够将此归因于以下事实:数据包之间实际上不存在争用,因为每个数据包逐步占用数组中的不同条目。然而,咱们实现中的次要毛病是咱们不解决数组满时的刷新,而它以循环形式执行写入。因而,它存储在任何工夫点察看到的最初几个数据包记录。尽管如此,它为咱们提供了通过在 eBPF 数据门路中适当利用数据结构来实现的一系列性能晋升。
(Kannan/Naik/Lev-Ran, CC BY-SA 4.0)
Multi-Flow
咱们当初测试具备多个流的 eBPF 察看代理的性能。咱们通过检测数据包生成器生成了 40 个不同的 UDP 流(每个外围 1 个流)。乏味的是,对于多个流,咱们察看到与单个流相比,每 CPU 哈希和哈希映射的性能存在显著差别。这可能归因于单个散列条目标争用缩小。然而,咱们没有看到 ringbuffer 有任何性能改良,因为无论流量如何,争用通道(即 ringbuffer)都是固定的。数组在多个流中的性能稍好一些。
学到了啥
依据咱们的钻研,咱们得出以下论断:
- 基于 ringbuffer 的每个数据包的解决不可扩大,并且会影响性能。
- Hash map 限度了数据流的突发流量,即每秒解决的数据包数量。每个 CPU 的 hash map 性能体现稍好。
- 思考到数组能够存储 10 个或 100 个数据包的记录,应用数组映射来存储每个数据包的明信片是解决数据流内数据包短时突发的一个不错抉择。这将确保察看代理能够接受短时间的突发,而不会升高性能。
在咱们的钻研中,咱们剖析了云中多个主机之间的数据包级和流级信息的监控。咱们首先假如可察看性的外围特色是如何以非侵入性形式收集数据。带着这种瞻望,咱们考察了现有工具,并测试了从 eBPF 数据门路中察看到的数据包中以流量指标的模式收集可观测性数据的不同办法。咱们钻研了用于收集流指标的数据结构如何影响流的性能。
现实状况下,为了最大限度地升高主机流量因可观测代理的开销而导致的性能降落,咱们的分析表明,能够混合应用每 CPU 数组和每 CPU 哈希数据结构。这两种数据结构能够一起应用,通过应用数组和每 CPU 哈希映射聚合来解决流量中的短时间突发。咱们目前正在设计可察看性代理,并打算在将来公布一篇文章,介绍设计细节和与现有工具的性能剖析。
翻译自:https://opensource.com/article/22/8/ebpf-network-observability-cloud
扩大浏览:
- 方法论:面向故障解决的可观测性体系建设
- 白皮书:事件 OnCall 核心建设办法
- 好工具:FlashDuty – 一站式告警解决平台:告警降噪、排班 OnCall