线上环境 Linux 系统调用追踪

提到如何动态追踪进程中的系统调用,相信你们第一时间都能想到 strace,它的基本用法很是简单,很是适合用来解决 “为何这个软件没法在这台机器上运行?” 这类问题。但若是须要分析线上服务 (特别是延迟敏感型)的某些系统调用的延迟时,strace 则不那么合适,由于它引入的开销会很是大,从性能分析大师 Brendan Gregg 的测试结果得知,被 strace 追踪的目标进程的运行速度会下降 100 倍以上,这对生产环境来讲将是个灾难。前端

那么是否有比较好用的工具用在生产环境上呢?答案是确定的,下面将介绍两款工具的经常使用命令,方便你们须要时查阅。api

Perf

众所周知,perf 是 Linux 系统下很是强大的性能工具,由 Linux 内核开发人员在不断演进和优化。除了能够分析 PMU (Performance Monitoring Unit) 硬件事件,内核事件等通用功能外,perf 还提供了其余“子模块”,好比 sched 分析调度器,timechart 根据负载特征可视化系统行为,c2c 分析可能存在的 false sharing (RedHat 在大量 Linux 的应用上,测试过这套 c2c 的开发原型,成功地发现了不少热点的伪共享缓存行问题。)等, 而 trace 则可用于分析系统调用,其功能很是强大,并保证了能够接受的开销—— 运行速度仅放慢 1.36 倍(dd 做为测试负载) 。咱们一块儿看下几个经常使用的场景:缓存

  1. 调用 syscall 数量的 top 排行榜数据结构

    perf top -F 49 -e raw_syscalls:sys_enter --sort comm,dso --show-nr-samples

    从输出能够看到在采样期间,kube-apiserver 的调用 syscall 的次数最多。架构

  2. 显示超过必定延迟的系统调用信息ssh

    perf trace --duration 200

    从输出中能够看到进程名称、pid ,超过 200 ms 的具体系统调用参数和返回值。工具

  3. 统计某个进程一段时间内系统调用的开销oop

    perf trace -p $PID  -s

    从输出中能够看到各系统调用的次数,返回错误次数,总延迟,平均延迟等信息。性能

  4. 咱们也能够进一步分析高延迟的调用栈信息测试

    perf trace record --call-graph dwarf -p $PID -- sleep 10

  5. 对一组任务进行 trace,好比后台有 2 个 bpf 工具在运行,咱们想看下它们系统调用使用状况,就能够先将它们添加到 perf_event 这个 cgroup 下,再执行 perf trace:

    mkdir /sys/fs/cgroup/perf_event/bpftools/
    echo 22542 >> /sys/fs/cgroup/perf_event/bpftools/tasks
    echo 20514 >> /sys/fs/cgroup/perf_event/bpftools/tasks
    perf trace -G bpftools -a -- sleep 10

perf-trace 的使用就介绍到这里,更多的用法请参考 man 手册,从上面能够看到 perf-trace 的功能很是强大,根据 pid 或 tid 就能够进行过滤。但彷佛没有对容器和 K8S 环境进行便捷的支持。不用着急,接下来介绍的这个工具就是针对容器和 K8S 环境的。

Traceloop

对于 Traceloop 你们可能有点陌生,但提到 BCC 想必你们就以为熟悉了。BCC 的前端是 Python/C++,其所属 iovisor 下还有一个项目叫 gobpf 是 BCC 的 go binding。而 Traceloop 则是基于 gobpf 库进行开发的,此项目的主要目标应用场景是容器、K8S 环境。其原理比较简单,其架构如图所示:

核心步骤以下:

  1. 利用 bpf helper 获取 cgroup id,根据 cgroup id 而不是 pid、tid 进行过滤。
  2. 每一个 cgroup id 对应一个 bpf tail call,经过这种方式实现对此 cgroup id 对应的 perf ring buffer 进行写入。
  3. 用户空间根据 cgroup id 读取对应的 perf ring buffer。

须要注意的是,当前 cgroup id 的获取方式是经过 bpf helper:bpf_get_current_cgroup_id 来获取的,这个 id 是 cgroup v2 才有的。所以只适用于开启了 cgroup v2 的环境。尚不肯定此项目团队是否有意向经过读取 nsproxy 数据结构等方式来对 cgroup v1 进行支持,所以在这里只作简单介绍。随着 K8S 1.19 版本开始支持 cgroup v2,期待 cgroup v2 能尽快普及起来。如下使用 Centos 8 4.18 版本内核进行简单的演示:在 traceloop 退出时 dump 系统调用信息

sudo -E ./traceloop cgroups  --dump-on-exit /sys/fs/cgroup/system.slice/sshd.service

从输出中能够看到,其输出和 strace/perf trace 相似,只是针对 cgroup 进行过滤。须要注意的是 Centos 8 没有像 Ubuntu 将 cgroup v2 挂载到 /sys/fs/cgroup/unified,而是直接挂载到 /sys/fs/cgroup 下,在使用前建议执行 mount -t cgroup2 来肯定挂载信息。

对于 K8S 平台,该团队将 traceloop 集成到 Inspektor Gadget 项目中,经过 kubectl 插件来运行,因为管网给出详细的 gif 示例,在这里就不作过多介绍了,对 cgroup v2 有需求的朋友能够试一试。

Benchmark

从 benchmark 结果看,strace 的引发的目标程序性能降低最大,perf trace 次之,traceloop 最小。

总结

strace 依然是解决 “为何这个软件没法在这台机器上运行?” 相关问题的利器,但对于分析系统调用延迟等问题,perf trace 是合适的选择,其也是基于 BPF 的实现,对于使用 cgroup v2 的容器、K8S 环境,traceloop 会更方便一些。

相关文章
相关标签/搜索