乐趣区

关于linux:SysAK-应用抖动诊断篇-eBPF又立功了-龙蜥技术

简介:且看 SysAK 是如何打造一款性能开销不大、安全可靠、且灵便的关中断检测工具。

文 / 零碎运维 SIG

编者按:还记得已经风行一时的狄仁杰探案系列之《他抖任他抖,IO 诊断在我手》、《netinfo:揭开网络抖动面纱的神器》、《coredump 瘦身风波》等带大家领略了青囊在网络、IO、内存等畛域叱咤风云的魅力。现在,零碎运维 SIG 组重磅归来,后面已介绍了 Kernel module 凑合 IO 夯,明天持续分享 eBPF 硬扛零碎中断,快随我一起来看看 SysAK 是如何打造一款性能开销不大、安全可靠、且灵便的关中断检测工具。

一、背景

日常业务运行时会常常受到各种各样的烦扰而产生抖动、影响客户体验。其中的一种干扰源是关中断,当关中断过久时可能会导致业务过程调度不及时、数据收发提早等,这种烦扰曾经随同 Linux 内核存在很长时间了,因此 Linux 内核包含业界也有不少相干的关中断检测伎俩。这里列举几个比拟典型计划:

1、内核最大关中断查看

内核本身在零碎中所有的关 / 开中断门路中增加了 TRACE_IRQ_OFF 的 trace 点,以对系统中所有开 / 关中断进行监控。

长处:关中断检测准确且全面,同时课观测到关中断的工夫、甚至堆栈。

毛病:依赖于 CONFIG_IRQSOFF_TRACER 内核配置,该配置在不少发行版不反对。插桩点太多而且是热门路,对性能影响较大。

2、watchdog/hardlock detecter

内核注册一个 PMU 硬件 event 定期检查本人注册的 watchdog hrtimer 中断是否有及时更新工夫戳。

长处:周期性的检测,对性能影响小,实用于零碎中关中断或者中断解决有 BUG 的状况。

毛病:监控的粒度太大,无奈提供更细粒度级别的零碎察看指标。对于一些无 PMU 硬件 event 的虚拟化环境该计划不失效。

3、trace_irq_handler_exit/trace_irq_handler_exit && irq_enter/irq_exit

在所有中断处理函数的入口 / 进口安插 trace 以及工夫记录。

长处:提供所有中断解决时长的原始数据。

毛病:只可能察看到中断解决的工夫状况,对于其余关中断门路无奈监控,没有 threshold 触发机制,须要人工预先剖析。

4、其余开源查看工具

在 Github 上也有不少相干的关中断查看工具,它们以 .ko 模块形式提供,利用 hrtimer 定时器查看到期工夫是否超过预期工夫。

长处:周期采样系统开销不大,提供了毫秒级的监控粒度。

毛病:以第三方模块形式提供,稳定性无奈保障。hrtimer 作为一般中断,须要等到关中断复原后能力检测到,精确度无奈保障。同时,对于中断函数提早的状况会失落掉前一个中断的信息。

下面的各个检测机制各有千秋,也有各自的缺点和不满足的场景。且看 SysAK 是如何打造一款性能开销不大、安全可靠、且灵便的关中断检测工具。

二、技术抉择

下面的工具选用的技术、实现伎俩和检测逻辑不同,导致了在不同场景中有着不同的场景中有着不同的优劣。而对于生产环境而言,监控工具的稳定性和工具的开销是比拟重要的思考因素。因此在内核热门路应用插桩以及应用内核模块的形式都不是太现实的抉择:前者可能在某些场景下对性能产生较大影响,后者对于内核模块的编码安全性要求十分高,稍不留神容易引发零碎宕机,对于批量部署的生产环境危险太大。

面对下面两个问题有没有计划或者技术手段可能解决呢?当然有。

针对内核模块的平安问题,eBPF 相对是 Linux 业界以后最好的解决方案,不仅平安而且还提供了大量易用的库来晋升编程体验。

而热门路插桩的性能问题,在关中断工夫过长这个场景中,应用定时采样、查看的形式即可解决,而采样当首选的还是 perf 事件采样。

三、方案设计

针对后面的背景和利用场景剖析初步实现了技术选型,此时关中断检测工具大抵原理也根本有了原型:

如果零碎反对 perf 硬件采样 (HW) 事件,首先应用 eBPF 启动一个内核定时器,定时器周期性产生中断并在中断处理函数中定时更新一个标记,而后 perf HW 事件再周期查看该标记是否按时更新,以此来判断时钟中断是否有按时产生或者延时产生的状况。

对于不反对 perf HW 的零碎,咱们无奈利用 perf HW 事件了。退而求其次,咱们同样通过 eBPF 须要启动内核定时器,定时器中断函数会查看本次定时器中断到期工夫与预期工夫是否有差别,以此来判断中断是否有提早的状况。

四、技术实现

实际上要实现下面的性能,须要解决如下几个问题:

1) eBPF 如何装置定时器?

2) 如何把 perf 事件触发后咱们的查看逻辑挂接到 perf 事件回调解决中?

3) 如何依据零碎对于 perf 硬件采样事件的反对与否让 eBPF 抉择不同的查看机制?

1、eBPF 装置定时器

在后面设计剖析中,咱们理解到要应用 eBPF 启动内核定时器来做一个中断样本。不过很不巧,eBPF 在 Linux-5.15 以下的内核版本不反对定时器创立。幸好条条路线通罗马,perf SW 事件中的 PERF_COUNT_SW_CPU_CLOCK 的事件其在 Linux 内核的底层就是通过高精度时钟实现的。因而只有奇妙的利用利用了这个原理,而后联合 eBPF 就能实现咱们须要的 eBPF 定时器。

2、eBPF prog 处理函数关联到 perf HW/SW 事件 overflow 回调函数

尽管 perf 在用户态提供来 perf_event_open 零碎调用和 ioctl 形式来创立 perf HW 和 perf SW 事件采样(如后面 PERF_COUNT_SW_CPU_CLOCK 事件,以及 perf 硬件事件 PERF_COUNT_HW_CPU_CYCLES,通过 man perf_event_open 查看更具体的信息),然而传统的用户态 perf 应用中并不能在这些事件触发后在内核去施行咱们想要的 hack 动作,例如执行咱们须要进行关中断检测的回调函数,只可能在内核代码或者内核模块中调用 perf_event_create_kernel_counter 函数注册咱们须要的回调函数到 perf 事件的 overflow_handler 上达成咱们的目标。

然而这个困境随着 eBPF 的呈现带来了变动。Perf event 为 ebpf 提供了专门的 ioctl 通道,以便为 ebpf 在内核中施展它的超能力(别忘了 eBPF 代码实质上还是在内核执行)。而 eBPF 与用户态又有着人造的 ” 亲和力 ”,这样用户态就能够十分不便的通过 ioctl 往 perf 事件挂接本人的回调解决逻辑。在代码层面上就是利用:

ioctl(PERF_EVENT_IOC_SET_BPF)

来将 eBPF prog 处理函数注册到 perf event 的 overflow_handler 回调解决中。

3、针对零碎是否反对 perf HW 事件抉择不同的查看策略

通过 perf_event_open 零碎调用的返回值判断零碎是否反对 perf HW 事件。

同时在 eBPF 中定义两组 prog,如果反对 perf HW 则 attach HW 事件检测的 prog,否则 attach SW 事件检测的 prog。

五、运行流程

本章次要对工具的实现做一个具体的合成。下图是工具运行的一个简略原理图:

整个流程如下:

1. 首先进行参数解析,包含阈值、运行工夫、日志记录文件指定等等参数对解析。

2. 进行 eBPF 初始化,这一步次要是加载 eBPF 程序。

3. 装置 eBPF 事件。首先创立 perf event,接着将 ebpf prog attach 关联到 perf event,最初创立一个 poll event,并监听。于此同时 perf event 开始工作,perf event 触发后将调用 eBPF prog 程序运行。eBPF prog 程序检测到阈值事件后唤醒用户态到 poll 工作。

4. 用户态 poll 被唤醒后将后果写到日志文件。

六、工具应用

装置 SysAK 后,应用如下命令:

sysak irqoff [--help] [-t THRESH(ms)] [-f LOGFILE] [duration(s)]

-t:关中断的门限值,单位是 ms。

-f:指定 irqoff 后果记录的文件。

duration:工具的运行时长,如果不指定默认会始终运行。

通过内核模块创立 worker 来结构了一个长时关中断的场景,上面是通过 irqoff 抓取的后果展现。

TIME(irqoff)          CPU       COMM            TID           LAT(us)
2022-05-05_11:45:19    3       kworker/3:0     379531        1000539
<0xffffffffc04e2072> owner_func
<0xffffffff890b1c5b> process_one_work
<0xffffffff890b1eb9> worker_thread
<0xffffffff890b7818> kthread
<0xffffffff89a001ff> ret_from_fork

后果中有若干局部组成:

第一行是 log header。总共 5 列,从左到右顺次是 工夫戳(模块信息)、关中断长的 CPU、关中断长的 current 线程 ID、总的关中断延时。

第二行对应 log header 的理论信息。

第三行及前面是抓取到关中断的现场堆栈信息,不便进行下一步对源码进行剖析。

原文链接
本文为阿里云原创内容,未经容许不得转载。

退出移动版